Greasy Fork

Greasy Fork is available in English.

MouseHunt Enhanced Search (Beta)

Improve the search logic of search bars in the game

当前为 2022-06-13 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         MouseHunt Enhanced Search (Beta)
// @description  Improve the search logic of search bars in the game
// @author       LethalVision
// @version      0.5
// @match        https://www.mousehuntgame.com/*
// @match        https://apps.facebook.com/mousehunt/*
// @icon         https://www.google.com/s2/favicons?domain=mousehuntgame.com
// @grant        none
// @license      MIT
// @namespace    http://greasyfork.icu/en/users/683695-lethalvision
// ==/UserScript==

// reference dictionaries
const CHEESE = {
    "Ancient String Cheese":"ASC","Bland Queso":"BQ","Brie String Cheese":"BSC","Checkmate Cheese":"CMC","Cloud Cheesecake":"CCC","Coggy Colby Cheese":"CCC",
    "Dragonvine Cheese":"DVC","Empowered SUPER|brie+":"ESB","Extra Rich Cloud Cheesecake":"ERCC","Festive Feta":"FF","Fishy Fromage":"FF","Fusion Fondue":"FF",
    "Galleon Gouda":"GGC","Gauntlet String Cheese":"GSC","Glazed Pecan Pecorino Cheese":"GPP","Glowing Gruyere Cheese":"GGC","Lactrodectus Lancashire Cheese":"LLC",
    "Limelight Cheese":"LLC","Magical Rancid Radioactive Blue Cheese":"MRRBC","Magical String Cheese":"MSC","Maki String Cheese":"MSC","Master Fusion Cheese":"MFC",
    "Nian Gao'da Cheese":"NGD","Null Onyx Gorgonzola":"NOG","Pecan Pecorino Cheese":"PPC","Polluted Parmesan Cheese":"PPC","Radioactive Blue Cheese":"RBC",
    "Rancid Radioactive Blue Cheese":"RRBC","Rift Rumble Cheese":"RRC","Runic String Cheese":"RSC","Sky Pirate Swiss Cheese":"SPS","Speedy Coggy Colby":"SCC",
    "Terre Ricotta Cheese":"TR","Undead Emmental":"UE","Undead String Emmental":"USE","Vanilla Stilton Cheese":"VSC","Vengeful Vanilla Stilton Cheese":"VVSC",
    "Wicked Gnarly Cheese":"WGC","Wildfire Queso":"WF"
}
const CHARMS = {
    "Baitkeep Charm":"BKC","Brilliant Water Jet Charm":"BWJC","Compass Magnet Charm":"CMC","Dragonbane Charm":"DBC","Eggscavator Charge Charm":"ECC",
    "Eggstra Charge Charm":"ECC","Ember Charm":"EC","Empowered Anchor Charm":"EAC","Extreme Ancient Charm":"EAC","Extreme Attraction Charm":"EAC",
    "Extreme Dragonbane Charm":"EDBC","Extreme Luck Charm":"ELC","Extreme Party Charm":"EPC","Extreme Polluted Charm":"EPC","Extreme Power Charm":"EPC",
    "Extreme Queso Pump Charm":"EQPC","Extreme Snowball Charm":"ESC","Extreme Spooky Charm":"ESC","Extreme Wealth Charm":"EWC","Factory Repair Charm":"FRC",
    "Festive Anchor Charm":"EAC","Festive Ultimate Luck Charm":"FULC","Festive Ultimate Lucky Power Charm":"FULPC","Festive Ultimate Power Charm":"FUPC","Forgotten Charm":"FC",
    "Gloomy Gathering Charm":"GGC","Lantern Oil Charm":"LOC","Let It Snow Charm":"LISC","Luck Charm":"LC","Lucky Power Charm":"LPC","Party Charm":"PC","Polluted Charm":"PC",
    "Power Charm":"PC","Prospector's Charm":"PC","Queso Pump Charm":"QPC","Realm Ripper Charm":"RRC","Rift 2020 Charm":"R2020","Rift 2021 Charm":"R2021",
    "Rift 2022 Charm":"R2022","Rift Extreme Luck Charm":"RELC","Rift Extreme Power Charm":"REPC","Rift Extreme Snowball Charm":"RESC","Rift Luck Charm":"RLC",
    "Rift Power Charm":"RPC","Rift Snowball Charm":"RSC","Rift Spooky Charm":"RSC","Rift Super Luck Charm":"RSLC","Rift Super Power Charm":"RSPC",
    "Rift Super Snowball Charm":"RSSC","Rift Super Vacuum Charm":"RSVC","Rift Ultimate Luck Charm":"RULC","Rift Ultimate Lucky Power Charm":"RULPC",
    "Rift Ultimate Power Charm":"RUPC","Rift Ultimate Snowball Charm":"RUSC","Rift Vacuum Charm":"RVC","Rift Wealth Charm":"RWC","Small Power Charm":"SPC",
    "Smart Water Jet Charm":"SWJC","Snowball Charm":"SC","Spooky Charm":"SC","Spore Charm":"SC","Super Ancient Charm":"SAC","Super Attraction Charm":"SAC",
    "Super Cactus Charm":"SCC","Super Dragonbane Charm":"SDBC","Super Lantern Oil Charm":"SLOC","Super Luck Charm":"SLC","Super Party Charm":"SPC","Super Polluted Charm":"SPC",
    "Super Power Charm":"SPC","Super Queso Pump Charm":"SQPC","Super Snowball Charm":"SSC","Super Spooky Charm":"SSC","Super Spore Charm":"SSC","Super Wealth Charm":"SWC",
    "Timesplit Charm":"TSC","Ultimate Anchor Charm":"UAC","Ultimate Ancient Charm":"UAC","Ultimate Attraction Charm":"UAC","Ultimate Charm":"UC ",
    "Ultimate Dragonbane Charm":"UDBC","Ultimate Luck Charm":"ULC","Ultimate Lucky Power Charm":"ULPC","Ultimate Party Charm":"UPaC","Ultimate Polluted Charm":"UPC",
    "Ultimate Power Charm":"UPC","Ultimate Snowball Charm":"USC","Ultimate Spooky Charm":"USC","Ultimate Spore Charm":"USC","Ultimate Wealth Charm":"UWC","Unstable Charm":"UC ",
    "Water Jet Charm":"WJC","Wealth Charm":"WC","Winter Charm":"WC"
}
const CRAFTING = {
    "Bottled Cold Fusion":"BCF","Calcified Rift Mist":"CRM","Chrome Celestial Dissonance Upgrade Kit":"CCDT","Chrome MonstroBot Upgrade Kit":"CMBT",
    "Chrome Oasis Upgrade Kit":"COWNT CPOT","Chrome School of Sharks Upgrade Kit":"CSOS","Chrome Sphynx Wrath Upgrade Kit":"CSW",
    "Chrome Storm Wrought Ballista Upgrade Kit":"CSWBT","Chrome Temporal Turbine Upgrade Kit":"CTT","Chrome Thought Obliterator Upgrade Kit":"CTOT CTHOT CF2",
    "Essence of Destruction":"EOD","Ful'Mina's Tooth":"Fulmina","Magic Essence":"ME","Predatory Processor":"PP","Really, Really Shiny Precious Gold":"RRSPG",
    "Sandblasted Metal":"SBM","Stale SUPER brie+":"stale SB","Temporal Shadow Plate":"TSP"
}
const SPECIAL = {
    "Adorned Empyrean Jewel":"AEJ","Bottled Wind":"BW","Champion's Fire":"CF","Evil Extract":"EE","Fire Bowl Fuel":"FBF","Ful'Mina's Gift":"fulmina",
    "Ful'mina's Charged Toothlet":"fulmina","Geyser Smolder Stone":"GSS","King's Credit":"KC","Magic Nest Dust":"MND","Quantum Quartz":"QQ","Rare Map Dust":"RMD",
    "Reactive Reagent":"RR","SUPER|brie+ Supply Pack":"SB","Sand Dollar":"SD","Sky Pirate Seal":"SPS","Snowball Showdown Dust":"SSD","Spooky Shuffle Dust":"SSD",
    "Timesplit Rune":"TSR","Wild Tonic":"WT","Sky Sprocket":"HAL_high altitude loot","Skysoft Silk":"HAL_high altitude loot","Enchanted Wing":"HAL_high altitude loot",
    "Cloudstone Bangle":"HAL_high altitude loot","Sky Glass":"glore","Sky Ore":"glore"
}
const WEAPON = {
    "Ancient Box Trap":"ABT","Ancient Spear Gun":"ASG","Anniversary Ancient Box Trap":"AABT","Anniversary Arcane Capturing Rod Of Never Yielding Mystery":"AACRONYM",
    "Anniversary Reaper's Perch":"ARP","Arcane Capturing Rod Of Never Yielding Mystery":"ACRONYM","Biomolecular Re-atomizer Trap":"BRAT","Birthday Party Piñata Bonanza":"Pinata",
    "Blackstone Pass Trap":"BPT_BSP","Blazing Ember Spear Trap":"BEST","Cackle Lantern Trap":"CLT","Celestial Dissonance Trap":"CDT","Christmas Crystalabra Trap":"CCT",
    "Chrome Arcane Capturing Rod Of Never Yielding Mystery":"CACRONYM","Chrome Celestial Dissonance Trap":"CCDT","Chrome Grand Arcanum Trap":"CGAT","Chrome MonstroBot":"CMB",
    "Chrome Oasis Water Node Trap":"COWNT","Chrome Phantasmic Oasis Trap":"CPOT","Chrome RhinoBot":"CRB","Chrome School of Sharks Trap":"CSOS","Chrome Sphynx Wrath":"CSW",
    "Chrome Storm Wrought Ballista Trap":"CSWBT","Chrome Temporal Turbine":"CTT","Chrome Thought Obliterator Trap":"CTOT_CTHOT_CF2","Circlet of Pursuing Trap":"A2",
    "Circlet of Seeking Trap":"A1","Clockwork Portal Trap":"CPT","Crystal Crucible Trap":"CCT","Crystal Tower":"CT","Dragon Slayer Cannon":"DSC","Droid Archmagus Trap":"DAT",
    "Ember Prison Core Trap":"EPCT","Endless Labyrinth Trap":"ELT","Enraged RhinoBot":"ERB","Event Horizon Trap":"EHT","Festive Forgotten Fir Trap":"FFFT",
    "Focused Crystal Laser":"FCL","Gouging Geyserite Trap":"GGT","Grand Arcanum Trap":"GAT","Horrific Venus Mouse Trap":"HVMT","Ice Maiden":"IM","Icy RhinoBot":"IRB",
    "Infinite Labyrinth Trap":"ILT","Infinite Winter Horizon Trap":"IWHT","Meteor Prison Core Trap":"MPCT","Multi-Crystal Laser":"MCL","Mutated Venus Mouse Trap":"MVMT",
    "Mysteriously unYielding Null-Onyx Rampart of Cascading Amperes":"MYNORCA","New Horizon Trap":"NHT","Oasis Water Node Trap":"OWNT","Obvious Ambush Trap":"OAT",
    "Phantasmic Oasis Trap":"POT","Pumpkin Pummeler":"PP","Queso Factory Trap":"QFT","Queso Fount Trap":"QFT","Reaper's Perch":"RP","RhinoBot":"RB","Rune Shark Trap":"RST",
    "S.A.M. F.E.D. DN-5":"SAMFED DN5_SAM FED DN5","S.L.A.C.":"SLAC","S.L.A.C. II":"SLAC2_SLAC 2","S.S. Scoundrel Sleigher Trap":"SSSST_S4T","S.T.I.N.G. Trap":"STING_L1",
    "S.T.I.N.G.E.R. Trap":"STINGER_L2","Sandstorm MonstroBot":"SMB","Scarlet Ember Root Trap":"SERT","School of Sharks Trap":"SOS","Sleeping Stone Trap":"SST_T1",
    "Slumbering Boulder Trap":"SBT_T2","Smoldering Stone Sentinel Trap":"SSST","Snow Barrage":"SNOB","Sphynx Wrath":"SW","Steam Laser Mk. I":"MK1_MK 1_MARK 1",
    "Steam Laser Mk. II":"MK2_MK 2_MARK 2","Steam Laser Mk. II (Broken!)":"MK2_MK 2_MARK 2","Steam Laser Mk. III":"MK3_MK 3_MARK 3","Storm Wrought Ballista Trap":"SWBT",
    "Tarannosaurus Rex Trap":"TREX","Temporal Turbine":"TT","The Forgotten Art of Dance":"FART","Thorned Venus Mouse Trap":"TVMT","Thought Manipulator Trap":"TMT_F1",
    "Thought Obliterator Trap":"TOT_THOT_F2","Timesplit Dissonance Trap":"TDT_TDW_TSD_TSW","Venus Mouse Trap":"VMT","Wacky Inflatable Party People Trap":"WIPPT",
    "Zugzwang's First Move":"ZFM","Zugzwang's Last Move":"ZLM","Zugzwang's Ultimate Move":"ZUM"
}
const BASE = {
    "Adorned Empyrean Refractor Base":"AERB","All Season Express Track Base":"ASETB","Attuned Enerchi Induction Base":"AEIB","Bronze Tournament Base":"BTB",
    "Claw Shot Base":"CSB","Clockwork Base":"CWB","Deep Freeze Base":"DFB","Denture Base":"DB","Desert Heater Base":"DHB","Elixir Exchanger Base":"EEB",
    "Enerchi Induction Base":"EIB","Gift of the Day Base":"GOTDB","Golden Tournament Base":"GTB","Iceberg Boiler Base":"IBB","Molten Shrapnel Base":"MSB",
    "Overgrown Ember Stone Base":"OESB","Prestige Base":"PB","Seasonal Gift of the Day Base":"SGOTDB","Signature Series Denture Base":"SSDB","Silver Tournament Base":"STB",
    "Treasure Seeker Base":"TSB","Ultimate Iceberg Base":"UIB","Wooden Base":"WB","Wooden Base with Target":"WBWTB"
}

// piggyback on Mousehunt's jQuery
// this is a smart thing to do that will never backfire on me
var $ = $ || window.$;

// one-time init functions go here
function init() {
    initMp();
    initTrap();
    initInv();
}

// == Marketplace Search ==
function initMp() {
    // extend templateutil.render to inject desired search terms
    const _parentRender = hg.utils.TemplateUtil.render;
    hg.utils.TemplateUtil.render = function(templateType, templateData) {
        if (templateType == 'ViewMarketplace_search') {
            // only edit marketplace search
            templateData.search_terms.forEach(category => updateMpSearch(category));
        }
        return _parentRender(templateType, templateData);
    }
}
function updateMpSearch(category) {
    var refDict = getDict(category.name);
    if (!refDict) { // invalid name
        return;
    }
    category.terms.forEach(function(listing) {
        if (refDict[listing.value] && listing.value.indexOf('hidden') == -1) {
            // update listing if it exists in reference dict
            // skip if the listing already has "hidden" tag added
            listing.value += `<span class="hidden">${refDict[listing.value]}</span>`;
        }
    });
}

// == Trap Setup Search ==
function initTrap() {
     // hook into ajax calls that get trap component info and modify the response
    var callback = function(options, originalOptions, jqXHR) {
        const componentUrl = 'managers/ajax/users/gettrapcomponents.php';
        if (options.url.indexOf(componentUrl) != -1) {
            var _parentSuccess = originalOptions.success || options.success;
            var _extendedSuccess = function (data) {
                if (data.components && data.components.length > 0) {
                    // console.log(data.components);
                    data.components.forEach(component => updateTrapSearch(component));
                }
                _parentSuccess(data);
            };
            originalOptions.success = options.success = _extendedSuccess;
        }
    }
    $.ajaxPrefilter(callback);

    // clean up the tag dropdown
    const _parentToggle = app.pages.CampPage.toggleItemBrowser;
    app.pages.CampPage.toggleItemBrowser = function(itemClassification, hasPresetFilters) {
        var returnValue = _parentToggle(itemClassification, hasPresetFilters);
        // Find and add onclick to the tag dropdown (select element) when the trap components are clicked
        var query = document.querySelectorAll('select[data-filter=tag]');
        if (query && query.length > 0) {
            var selectElem = query[0];
            // remove the custom tags we added for the enhanced search
            selectElem.onclick = function() {
                var ignoreList = ['no_tag_selected','recommended','default'];
                var tagList = app.pages.CampPage.getTags();
                for (var i=0; i<selectElem.length; i++) {
                    var optValue = selectElem.options[i].value;
                    if (!ignoreList.includes(optValue) && !tagList[optValue]) {
                        selectElem.remove(i);
                        i--; // options now has one less element
                        // console.log(`Removed ${optValue}`);
                    }
                }
            }
        }
        return returnValue;
    }
}

function updateTrapSearch(component) {
    var refDict = getDict(component.classification);
    if (!refDict) { // invalid name
        return;
    }
    if (refDict[component.name]) {
        // add a tag to the trap component with its reference dict acronym
        if (component.tag_types) {
            component.tag_types.unshift(refDict[component.name]);
        } else {
            // create the tag_types array if it doesn't exist
            component.tag_types = [refDict[component.name]];
        }
    }
}

// == Inventory Search ==
// TODO: break this up for the different tabs? (cheese, crafting, special, etc.)
function initInv() {
    const inventoryUrl = 'managers/ajax/pages/page.php';
    const originalOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function() {
        this.addEventListener("load", function() {
            if ( this.responseURL.indexOf(inventoryUrl) != -1) {
                updateInventory();
            }
        });
        originalOpen.apply(this, arguments);
    };
}

function updateInventory() {
    var query = document.querySelectorAll('.inventoryPage-item:not(.tagged)');
    if (query && query.length > 0) {
        query.forEach(function(item){
            item.classList.add("tagged");
            var refDict = getDict(item.getAttribute('data-item-classification'))
            if (!refDict) { // invalid classification
                return;
            }
            var dataName = item.getAttribute('data-name');
            if (refDict[dataName]) {
                item.setAttribute('data-name', `${dataName}_${refDict[dataName]}`);
            }
        });
    }
}

// == helpers ==
// returns the appropriate reference dict given a classification string
// returns undefined if there is no match
function getDict(classification) {
    if (typeof classification === 'string') {
        switch(classification.toLowerCase()) {
            case 'cheese':
            case 'bait':
                return CHEESE;
                break;
            case 'charms':
            case 'trinket':
                return CHARMS;
                break;
            case 'crafting':
                return CRAFTING;
                break;
            case 'special':
            case 'stat':
                return SPECIAL;
                break;
            case 'weapon':
                return WEAPON;
                break;
            case 'base':
                return BASE;
                break;
        }
    }
    // no match
    return undefined;
}

// start script
init();