Greasy Fork

MouseHunt Custom Themes

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

目前为 2020-08-29 提交的版本。查看 最新版本

// ==UserScript==
// @name         MouseHunt Custom Themes
// @author       LethalVision
// @namespace    https://greasyfork.org/en/users/683695-lethalvision
// @version      0.5
// @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_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"]}
};

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

var preferences = {
    selection: "None"
};

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;
        } catch (err) {
            console.log('Preference parse error: ' + err);
        }
    }
    addListener();
    loadUrls(preferences.selection);
}

function loadUrls(selection) {
    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("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.isNaN || 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;
            break;
        case "bot":
            imgSizes.bot.width = width;
            imgSizes.bot.height = height;
            updateTheme();
            break;
        default:
            console.log(`setSize unrecognized portion: ${portion}`);
            return;
    }
}

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";
    mainDiv.appendChild(titleDiv);

    // 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;
    themeDiv.appendChild(themeSelect);
    mainDiv.appendChild(themeDiv);

    // setup button
    var loadButton = document.createElement("button");
    loadButton.textContent = "Load Theme";
    loadButton.style.marginTop = "5px";
    loadButton.style.marginBottom = "5px";
    loadButton.onclick = changeSelection;
    mainDiv.appendChild(loadButton);

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

function changeSelection() {
    var selectorElem = document.getElementById('selectTheme');
    var selectValue = selectorElem.value;
    // store preference
    preferences.selection = selectValue;
    var jsonString = JSON.stringify(preferences);
    window.localStorage.setItem(TAG, jsonString);
    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 (topUrl.length == 0 || midUrl.length == 0 || botUrl.length == 0){
        // skip update if urls are invalid
        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