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 提交的版本,查看 最新版本

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