Greasy Fork

MoxxiMod 8

one click at a time

目前为 2024-03-18 提交的版本。查看 最新版本

// ==UserScript==
// @name         MoxxiMod 8
// @namespace    https://studiomoxxi.com/
// @description  one click at a time
// @author       Ben
// @match        *.outwar.com/*
// @version      8.1
// @grant        GM_xmlhttpRequest
// @license      MIT
// @run-at       document-start
// @grant        GM_getResourceText
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// @grant        GM_xmlhttpRequest
// @grant        GM_addValueChangeListener
// @grant        unsafeWindow
// @require      http://code.jquery.com/jquery-3.6.0.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js
// @require      https://greasyfork.org/scripts/460904-canvas2image/code/Canvas2Image.js?version=1155383
// ==/UserScript==
/* globals jQuery, $, waitForKeyElements */

if (document.URL.match("mob.php") || document.URL.match("mob_talk") ) {
    return;
};


loadCustomTheme();


if (document.URL.match("outwar")) {

    GM_addStyle (`
    body > center > div.sub-header-container{display:none;z-index:9999;}
    body > center > div.header-container.fixed-top{display:none;}
    body > center > div.sub-header-container2{display:none;}
    body > center > div.sub-header-container > header{height:46px;box-shadow:0 5px 5px 0 rgba(0,0,0,1) !important;}
    #accordionExample{display:none;}
    body > center > div.sub-header-container{top:0px}
    #container{position:relative;top:-70px}
    #sidebar ul.menu-categories.ps{border-right:0px !important;top:-90px;z-index:100;}
    body > center > div.sub-header-container > header > ul.navbar-nav.flex-row.mr-auto.toolbar-nav > li:nth-child(1) > div > span{width:150px !important;}
    span.toolbarSpan{margin-left:7px;vertical-align:middle;}
    .form-control-new{display:inline-block;border: 1px solid #1b2e4b;color:#e6e6e6;letter-spacing:1px;padding-left:10px;padding-right:10px;background:#1b2e4b;font-size:18px;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);border-radius:5px;transition: .5s ease-out;}
    .form-control-new:hover{opacity:0.5;}
    .navbar{min-height: 0px !important;}
    .pop td {text-align:left;padding:2px;font-size:11px;color:#FFFFFF;}
    #language-dropdown > div > p.top-exp.mr-1.menu_mid_size{display:none !important;}
    #language-dropdown > div > p.top-rage{display:none;}
    body > center > div.sub-header-container > header > ul.navbar-nav.flex-row.mr-auto.toolbar-nav > li:nth-child(1) > div > span{display:none;}
    li.toolbarButtons{margin-right:13px;}
    #dropdownCharacters{width:180px !important;margin-left:1rem;font-weight:700;visibility:visible !important;}
    #dropdownRgas{visibility:visible !important;}
    .btn-mm{background-color:#060818;margin-left:3px;margin-right:3px;color:#FFFFFF;padding:.4375rem 1.25rem;font-size:14px;font-weight:400;transition: .5s ease-out;cursor:pointer;border-radius:10px;box-shadow: 0 5px 20px 0 rgba(0,0,0,.1);letter-spacing:2px;}
    .btn-mm:hover{filter: saturate(250%);opacity:0.75;}
    .pointer{cursor:pointer;}
    #content > div.footer-wrapper{display:none;}
    #container > div.footer-wrapper{display:none;}
    body img[src*="items/skillitem.jpg"] {content: url("https://studiomoxxi.com/moxximod/aneuro.webp") !important;}
    table.table{margin-bottom: 0rem;}
    .little-space{margin-top:0px;}
    .table td, .table th{padding:8px !important;}
    .bio .widget-content-area h3:after{display:none;}
    `);

    GM_addStyle (`
    #toolbarTiles img{width:29px;height:29px;border-radius:5px;margin-right:4px;}
    img.tile-still:hover{filter: saturate(250%);opacity:0.5;}
    img.tile-animate{cursor:pointer;transition: .5s ease-out;animation: fadeIn 1s ease-in-out forwards, tileanimate 1s infinite;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);}
    img.tile-still{cursor:pointer;transition: .5s ease-out;animation: fadeIn 1s ease-in-out forwards;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);}
    @keyframes fadeIn {from {opacity: 0;} to {opacity: 1;}}
    @keyframes tileanimate{0% {filter: saturate(100%);} 50% {filter: saturate(250%); } 100% {filter: saturate(100%);}}
    `);

    GM_addStyle (`
    #travelDiv{z-index:0;height:0px;box-shadow: 0 0 10px rgba(0, 0, 0, 1);overflow:auto;text-align:center;display:inline-block;}
    .travel-destination{width:300px;margin-bottom:7px;height:40px;padding:5px;text-align:left;}
    img.travel-img{height:25px;width:25px;border-radius:5px;margin-right:15px;margin-left:5px;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);}
    `);

    GM_addStyle (`
    #appsDiv{z-index:0;height:0px;box-shadow: 0 0 10px rgba(0, 0, 0, 1);overflow:hidden;text-align:left;}
    div.appDiv{display:inline-block;font-size:9px;text-align:center;font-family:monospace,monospace;width:95px;}
    img.app-img{background: linear-gradient(to bottom, #898989, #262626);height:60px;width:60px;margin:7px;border-radius:10px;padding:10px;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);box-shadow: inset 0.4em 0.4em 0.4em 0 rgba(255,255,255,0.8), inset -0.4em -0.4em 0.4em 0 rgba(0,0,0,0.8);cursor:pointer}
    img.app-img:hover{filter: saturate(250%);opacity:0.75;transition: .5s ease-out;}
    `);

    GM_addStyle (`
    #casterDiv{z-index:0;height:0px;box-shadow: 0 0 10px rgba(0, 0, 0, 1);overflow:hidden;text-align:center;}
    img.castable{height:35px;width:35px;margin:4px;border-radius:10px;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);background:#000000;cursor:pointer;transition: 0.25s ease-out;}
    img.castable:hover{filter: saturate(250%);opacity:0.5;}
    img.caster-selected{border:2px #00CC00 SOLID !important;width:35px !important;height:35px !important;padding:3px !important;}
    `);

    GM_addStyle (`
    #searchDiv{z-index:0;height:0px;box-shadow: 0 0 10px rgba(0, 0, 0, 1);overflow:hidden;text-align:center;}
    #searchDiv > form > input,#searchDiv > input{font-size:18px;}
    `);

    GM_addStyle (`
    #closeSkillsTab{cursor:pointer;}
    #skillsTab{position:fixed;top:55px;right:15px;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);padding:5px;font-size:11px;text-align:center;padding-top:10px;}
    #tabSkills > img{height:20px;width:20px;margin:4px;border-radius:5px;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);background:#000000;cursor:pointer;transition: .5s ease-out;}
    #tabBooster > img{height:30px;width:30px;margin:4px;border-radius:5px;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);background:#000000;cursor:pointer;transition: .5s ease-out;}
    #tabSpacer > hr{margin-top:5px;margin-bottom:5px;}
    `);

    GM_addStyle (`
    #itemtable > tbody > tr:nth-child(2) > td:nth-child(2) > img:nth-child(1){min-width:58px;}
    body img[src*="gem_green1"] {content: url("https://studiomoxxi.com/ow_themes/custom_jobs/classic_01/gem_green.webp") !important;width: 25px !important;margin:2px;border:0px solid #666666;margin-top:5px;}
    body img[src*="gem_blue2"] {content: url("https://studiomoxxi.com/ow_themes/custom_jobs/classic_01/gem_blue.webp") !important;width: 25px !important;margin:2px;border:0px solid #666666;margin-top:5px;}
    body img[src*="gem_red2"] {content: url("https://studiomoxxi.com/ow_themes/custom_jobs/classic_01/gem_red.webp") !important;width: 25px !important;margin:2px;border:0px solid #666666;margin-top:5px;}
    body img[src*="gem_white2"] {content: url("https://studiomoxxi.com/ow_themes/custom_jobs/classic_01/gem_white.webp") !important;width: 25px !important;margin:2px;border:0px solid #666666;margin-top:5px;}
    body img[src*="gemslot2"] {width: 30px !important;margin-bottom:5px;border:1px solid #666666;}
    #itemtable>tbody>tr:nth-child(2)>td:nth-child(2)>img:nth-child(8) {width: 25px !important;margin:4px !important;}
    #itemtable>tbody>tr:nth-child(2)>td:nth-child(2)>img:nth-child(9) {width: 25px !important;margin:4px !important;}
    #itemtable>tbody>tr:nth-child(2)>td:nth-child(2)>img:nth-child(10) {width: 25px !important;margin:4px !important;}
    #itemtable>tbody>tr:nth-child(2)>td:nth-child(2)>img:nth-child(11) {width: 25px !important;margin:4px !important;}
    #itemtable>tbody>tr:nth-child(2)>td:nth-child(2)>img:nth-child(12) {width: 25px !important;margin:4px !important;}
    `);

    GM_addStyle (`
    #authSlider{z-index:9999;height:0px;box-shadow: 0 0 10px rgba(0, 0, 0, 1);overflow:hidden;width:100%;text-align:center;color:#FFFFFF;position:fixed;font-weight:700 !important;font-size:20px;opacity:0;botom:0px;}
    `)

    GM_addStyle (`
    .mm-cell{background-color:#060818;}
    `)

    GM_addStyle (`
    #blankOverlay{height:100%;width:100%;z-index:1000;position:fixed;top:0px;border-radius:0px;opacity:0.99;}
    `)

    GM_addStyle (`
    #loadingOverlay{height:100%;width:100%;z-index:9999;position:fixed;top:0px;border-radius:0px;opacity:0.50;}
    #loadingOverlay > img{position:absolute;top:50%;left:50%;transform: translate(-50%,-50%);}
    `)

    GM_addStyle (`
    .dropdown-menu{box-shadow: 0px 0px 10px rgba(0, 0, 0, 1);}
    `)

    GM_addStyle(`
    img[src="images/store_head.jpg"]{display:none;}
    img[src="images/page/gladiator/Gladiator.png"]{display:none;}
    `)
};


let travelMenuCreated = false;
let appsMenuCreated = false;
let casterMenuCreated = false;
let searchMenuCreated = false;
let authSliderCreated = false;
let superfetchCache = {}


if (window.location.href.toString().match(/outwar\.com\/characters\/[0-9]+/i)){window.location = window.location.href.replace("characters/","profile?id=")};

$('head').append('<style>' +
    '#content { display: none; }' +
'</style>');


document.addEventListener("DOMContentLoaded", pageLoaded);


async function pageLoaded() {

    if (document.body.innerHTML.match('images/ErrorImg.jpg')){
        const errorMsg = document.body.innerHTML.match(/<font face="Verdana, Arial, Helvetica, sans-serif">(.*?)<\/font>/i)[1]
        alert(`ERROR: ${errorMsg}\nRedirecting to Outwar homepage.`);
        window.location.href = "home"
        return;
    };

    let serverNo;
    let server;
    if (window.location.toString().match('sigil')){
        serverNo = 1
        server = 'sigil'
    } else {
        serverNo = 2
        server = 'torax'
    };

    async function moxximod(){

        const rgaName = document.body.innerHTML.match(/rg_sess_id=([A-Za-z0-9]+)" target="_blank"/i)[1];
        const buyPointsLink = document.querySelector("#accordionExample > a").outerHTML.match(/href="([^"]*)">/i)[1];
        await updateRga(rgaName);

        const charId = document.body.innerHTML.match(/outwar\.com\/page\?x=([0-9]+)/i)[1]

        const toolbarData = document.querySelector("body > center > div.sub-header-container > header > ul.navbar-nav.flex-row.mr-auto.toolbar-nav").innerHTML
        const dataTime = toolbarData.match(/<p class="top-clock">\n(.*?) <\/p>/i)[1]
        const dataLevel = toolbarData.match(/<span class="toolbar_level">\n([0-9]+) <\/span>/i)[1]
        const dataRage = parseInt(toolbarData.replace(/,/g,'').match(/<span class="toolbar_rage">\n(.*?) <\/span>/i)[1])
        const dataExp = parseInt(toolbarData.replace(/,/g,'').match(/<span class="toolbar_exp">\n([0-9]+) <\/span>/i)[1])
        const dataEnhancementExp = parseInt(toolbarData.replace(/,/g,'').match(/<b>Enhancement Exp:<\/b><\/td><td>([0-9]+)<\/td><\/tr>/i)[1])
        const dataToLevel = toolbarData.match(/<b>Needed to Level:<\/b><\/td><td>(.*?)<\/td><\/tr>/i)[1]
        const dataGrowth = parseInt(toolbarData.replace(/,/g,'').match(/<b>Growth Today:<\/b><\/td><td>(.*?)<\/td><\/tr>/i)[1])
        const dataMinimum = parseInt(toolbarData.replace(/,/g,'').match(/<b>Minimum:<\/b><\/td><td>([0-9]+)<\/td><\/tr>/i)[1])
        const dataExpPerTurn = parseInt(toolbarData.replace(/,/g,'').match(/Growth Today:<\/b><\/td><td>.*?<\/td><\/tr><tr><td><b>Per Turn:<\/b><\/td><td>([0-9]+)<\/td><\/tr>/i)[1])
        const dataRagePerTurn = parseInt(toolbarData.replace(/,/g,'').match(/<tr><td><b>Per Turn:<\/b><\/td><td>([0-9]+)<\/td><\/tr><tr><td><b>Maximum:/i)[1])
        const dataMaximum = parseInt(toolbarData.replace(/,/g,'').match(/<b>Maximum:<\/b><\/td><td>([0-9]+)<\/td><\/tr>/i)[1])
        const dataGold = parseFloat(toolbarData.replace(/,/g, '').match(/<tr><td><b>Gold:<\/b><\/td><td>(.*)<\/td><\/tr>/i)[1]);
        const dataPoints = parseFloat(toolbarData.replace(/,/g, '').match(/<tr><td><b>Points:<\/b><\/td><td><font size=2 color=#00FF00>(.*)<\/font><\/td><\/tr>/i)[1]);
        const dataPremium = parseFloat(toolbarData.replace(/,/g, '').match(/Premium:<\/b><\/td><td><font size=2 color=#00FF00>.*?\.<\/font><font color=#00CC00>[0-9]+<\/font>/i).toString().replace("</font><font color=#00CC00>","").replace("Premium:</b></td><td><font size=2 color=#00FF00>","").replace("</font>",""));
        const dataSkillPoints = parseFloat(toolbarData.replace(/,/g, '').match(/<tr><td><b>Skill:<\/b><\/td><td>(.*)<\/td><\/tr>/i)[1]);
        const dataAttack = parseInt(toolbarData.replace(/,/g,'').match(/<b>Attack:<\/b><\/td><td>([0-9]+)<\/td><\/tr>/i)[1])
        const dataHp = parseInt(toolbarData.replace(/,/g,'').match(/<b>Hit Points:<\/b><\/td><td>([0-9]+)<\/td><\/tr>/i)[1])
        const dataCritical = parseInt(toolbarData.replace(/,/g,'').match(/<b>Critical:<\/b><\/td><td>([0-9]+)%<\/td><\/tr>/i)[1])
        const dataRampage = parseInt(toolbarData.replace(/,/g,'').match(/<b>Rampage:<\/b><\/td><td>([0-9]+)%<\/td><\/tr>/i)[1])
        const dataBlock = parseInt(toolbarData.replace(/,/g,'').match(/<b>Block:<\/b><\/td><td>([0-9]+)%<\/td><\/tr>/i)[1])
        const fetchTokens = await challengeStatus(server);
        const dataFreeTokens = fetchTokens.match('error') ? "NA" : parseInt(fetchTokens.match(/"tokens":"(.*?)"/i)[1]);
        const dataPremiumTokens = fetchTokens.match('error') ? "NA" : parseInt(fetchTokens.match(/"p_tokens":"(.*?)"/i)[1]);

        const profile = await superfetch('profile');

        await menu(rgaName,charId,serverNo,profile,buyPointsLink);
        await toolbar(charId,toolbarData,dataTime,dataLevel,dataRage,dataExp,dataEnhancementExp,dataToLevel,dataGrowth,dataMinimum,dataExpPerTurn,dataRagePerTurn,dataMaximum,dataGold,dataPoints,dataPremium,dataSkillPoints,dataFreeTokens,dataPremiumTokens,dataAttack,dataHp,dataCritical,dataRampage,dataBlock)

        const documentUrl = document.URL;
        if (documentUrl.match("profile") && !document.URL.match("crew_profile")) { await profilePage(); }
        else if (documentUrl.match("home") && !document.URL.match("crew_home") && !document.URL.match("homepost")) { await home(profile); }
        else if (documentUrl.match("world")){ await world(profile,server); }
        else if (documentUrl.match("cast_skills")){ await castSkills(); }
        else if (documentUrl.match("crew_profile")){ await crewProfile(); }
        else if (documentUrl.match("crew_vault")){ await crewVault(); }
        else if (documentUrl.match("trade")){ await trade(); }
        else if (documentUrl.match("godstatus")){ await godstatus(); }
        else if (documentUrl.match("crew_raidresults")){ await raidResults(); }
        else if (documentUrl.match("itemtransfer")){ await itemTransfer(); }
        else if (documentUrl.match("crew_bossspawns")){ await bossSpawns(); }
        else if (documentUrl.match("boss_stats")){ await bossStats(); }
        else if (documentUrl.match("changefaction")){ await changeFaction(profile); }
        else if (documentUrl.match("augmentequip")){ await augmentEquip(); }
        else if (documentUrl.match("closedpvp")){ await closedpvp(profile,server,charId); }
        else if (documentUrl.match("pointtransfer")){ await pointTransfer(dataPremium); }
        else if (documentUrl.match(/gladiator\?mobid=[0-9]+/i)){ await gladiator(charId,profile); }
        else if (documentUrl.match(/myaccount|editcharacters|support|accountinfo/)) { await myaccount(server); }
        else if (documentUrl.match("type=vision")){ await moxxivision(server,serverNo,rgaName,charId); }
        else if (documentUrl.match("exportrga")){ await exportrga(server,serverNo,rgaName,charId); }
        else if (documentUrl.match("blacksmith")){ await blacksmith(server,serverNo,rgaName,charId); }
        else if (documentUrl.match("support")){ await support(); }
        else if (documentUrl.match("spawntimeview")){ await oracle(); }
        return profile;
    };
    const profile = await moxximod();
    $('#content').show();

    //await timestampLoaded()
    //async function timestampLoaded(){
        //const ts = GM_getValue('ts');
        //var timestamp = new Date().getTime();
        //ts.push((timestamp-timestampStart)/1000);
        //GM_setValue('ts',ts);
    //};
    await parseAugments();
    await tiles(profile);
    await skillsTab(profile);
    await openPotionBp();
};


async function profilePage(){

    GM_addStyle (`
    #allAugs > img {height:30px;width:30px;margin:1px;border-radius:5px;border:2px #475254 SOLID;}
    #missingRobot, #skills > img {height:40px;width:40px;margin:3px;border-radius:5px;border:2px #475254 SOLID;}
    div.card-body{padding:0px;}
    #divHeaderName > font{text-transform: uppercase;font-size: 1.5em;font-weight: bold;margin-bottom: 1rem;}
    #pbuttons{margin:1rem !important;}
    #content > div > div:nth-child(1){max-width:350px !important;}
    #content > div > div:nth-child(2){max-width:800px !important;}
    .widget{padding:10px !important;}
    .progress{margin-bottom:0rem;}
    #UnderlingTable > thead > tr > th{padding:10px;margin:5px;margin-top:10px}
    #UnderlingTable > tbody > tr > td{padding:10px;margin:5px}
    #UnderlingTable > thead > tr > th,#UnderlingTable > tbody > tr > td{padding:3px;margin:0px;}
    #profileSlayerDiv > div > div > img {height:20px !important;}
    div.smallSlayerDiv {height:20px;width:20px;overflow:hidden;display:inline-block;}
    #UnderlingTable > thead > tr > th:nth-child(4){display:none;}
    #UnderlingTable > tbody > tr > td:nth-child(4){display:none;}
    div.profile-comments{text-align: left !important;}
    div.crestDiv > img{height:32px;width:32px;}
    `);


    let profileHeader = document.querySelector("#divHeader").innerHTML.replace(/[0-9]+ Profile Hits/i,'')
    const profileInfo = document.querySelectorAll('div.card')[0].innerHTML.replace(`<h5 class="card-title">PLAYER INFO</h5>`,"").replace(`<table class="table table-striped" cellpadding="0" cellspacing="0" width="100%">`,`<table class="charinfo" cellpadding="0" cellspacing="0" width="100%">`)
    const profileEq = document.querySelectorAll('div.card')[1].innerHTML.replace(`<h5 class="card-title">EQUIPMENT</h5>`,"").replace(`/images/thedude.png`,'https://studiomoxxi.com/moxximod/thedudeplus.png').replace('left:214px; top:346px;','left:10px; top:300px;').replace('left:258px; top:346px;','left:54px; top:300px;').replace('</div> </div>','')
    const profileCrests = document.querySelectorAll('div.card')[2].innerHTML.replace(`<h5 class="card-title">SKILL CRESTS</h5>`,"")
    const profileMastery = document.querySelectorAll('div.card')[3].innerHTML.replace(`<h5 class="card-title">MASTERIES</h5>`,"")
    const profilePic = document.querySelectorAll('div.card')[5].innerHTML.match(/src="([^"]*)"/i)[1]
    const profileSlayer = document.querySelectorAll('div.card')[9].innerHTML.replace(`</h5>`,`</h5><p>`).replace(/<div class="divGodSlayerImg" style="display: inline-block;height:50px;width:50px;background-image: url\(/g,`<div class="smallSlayerDiv"><img src=`).replace(/\); background-position: 0px;"/g,'').replace(/ onmouseout="kill\(\);"><\/div>/g,` onmouseout="kill();"></div>`)
    const profileLings = document.querySelector("#UnderlingTable").outerHTML.replace('table table-striped-dark mt-1','')
    const profileSkills = document.querySelector('#divSkillsCast').innerHTML.replace(/<img src="http:\/\/[A-Za-z]+\.outwar\.com\/images\/profile\/ProfileSkills\.png">/i,"");

    let uploadPicLink = '';
    if (document.querySelector("#divProfile > div:nth-child(2) > div > div > div.col-xl-8.col-md-7 > div > div:nth-child(1) > div > a") != null){
        GM_addStyle (`#uploadPicLinkDiv{margin-bottom:-25px;}`)
        uploadPicLink = document.querySelector("#divProfile > div:nth-child(2) > div > div > div.col-xl-8.col-md-7 > div > div:nth-child(1) > div > a").outerHTML;
    };

    if (document.querySelector("#divActions > a:nth-child(1)")){
        var playerAttack = document.querySelector("#divActions > a:nth-child(1)").outerHTML.replace(`<img src="http://torax.outwar.com/images/profile/ProfileAttack.png" alt="ATTACK" border="0">`,"").replace(`<img src="http://sigil.outwar.com/images/profile/ProfileAttack.png" alt="ATTACK" border="0">`,"").replace(`</a>`,"")
        var playerName = playerAttack.match(/<a href="javascript:void\(0\);" onclick="showAttackWindow\('([^']*)','([0-9]+)','[0-9]+','[^']*'\)">/i)[1]
        var playerId = playerAttack.match(/<a href="javascript:void\(0\);" onclick="showAttackWindow\('([^']*)','([0-9]+)','[0-9]+','[^']*'\)">/i)[2]
        }

    if (window.location.href.match("id") == null){
        GM_addStyle (`#pbuttons{display:none !important;}`)
    }
    if (playerAttack == undefined){GM_addStyle (`#atk_button{display:none !important;}`)}

    var isplayerpp = "no"

    if (profileHeader.match(/<img src="[^"]*" onmouseover="popup\(event,'Preferred Player','808080'\)" onmouseout="kill\(\)">/i) != null){
        profileHeader = profileHeader.replace(/<img src="[^"]*" onmouseover="popup\(event,'Preferred Player','808080'\)" onmouseout="kill\(\)">/i,"")
        isplayerpp = "yes"
    }

    if (isplayerpp == "yes"){
        profileHeader = profileHeader.replace(`<font size="3">`,`<font style="color:#E79A31;font-size:36px;letter-spacing:0.25rem;text-transform:uppercase;">`)
    } else {
        profileHeader = profileHeader.replace(`<font size="3">`,`<font style="font-size:36px;letter-spacing:0.25rem;text-transform:uppercase;">`)
    };


    document.querySelector("#content").innerHTML = `
    <div class="widget profile-widget" style="width:1115px !important;margin-top:0.5rem;">
    `+profileHeader+`<p>
    <span id="pbuttons">
    <button id="atk_button" class="btn-mm">`+playerAttack+`ATK</a></button>
    <button id="button" class="btn-mm"><a href=send_ow_message?name=`+playerName+`>MSG</a></button>
    <button id="button" class="btn-mm"><a href=profile?id=`+playerId+`&ally=1>ALLY</a></button>
    <button id="button" class="btn-mm"><a href=blocklist?id=`+playerId+`>BLOCK</a></button>
    <button id="button" class="btn-mm"><a href=trade?tradeWith=`+playerId+`>TRADE</a></button>
    <button id="button" class="btn-mm"><a href=crew_invites?inv=`+playerName+`>INVITE</a></button>
    <button id="button" class="btn-mm"><a href=profile?id=`+playerId+`&enemy=1>ENEMY</a></button>
    <button id="button" class="btn-mm"><a href=treasury?search_for=`+playerName+`>TREAS</a></button>
    </span>
    <div id="skills">`+profileSkills+`<span id="missing" style="text-align:right;opacity:1;"></span></div>
    </div>
    <div class="row justify-content-center">
    <div style="margin:1rem;max-width:350px;">
    <div class="widget widget-chart-one mb-3 profile-widget">
    <div>
    <span id="classLogo"></span><p>
    `+profileInfo+`
    <span id="isppspan"></span><p style="margin-top:10px">
    </div>
    </div>
    <div class="widget widget-chart-one mb-3 profile-widget">
    <h5 class="card-title">UNDERLINGS</h5><p></p>
    `+profileLings+`
    </div>
    </div>
    <div style="margin:1rem;max-width:350px;">
    <div class="widget widget-chart-one mb-3 profile-widget">
    `+profileEq+`
    <div style="position:absolute; left:258px; top:346px; width:32px; height:32px;text-align:center" class="crestDiv" id="classCrestDiv"></div>
    <div style="position:absolute; left:258px; top:300px; width:32px; height:32px;text-align:center" class="crestDiv" id="ferocityCrestDiv"></div>
    <div style="position:absolute; left:214px; top:346px; width:32px; height:32px;text-align:center" class="crestDiv" id="preservationCrestDiv"></div>
    <div style="position:absolute; left:214px; top:300px; width:32px; height:32px;text-align:center" class="crestDiv" id="afflictionCrestDiv"></div>
    </div></div>
    </div>
    <div class="widget widget-chart-one mb-3 profile-widget" style="max-width:350px">
    <h5 class="card-title">ALL AUGMENTS</h5><p></p>
    <span id="allAugs"></span>
    </div>
    </div>
    <div style="margin:1rem;max-width:350px;">
    <img src="`+profilePic+`" style="width:350px;max-height:350px;border-radius:8px;margin-bottom:1rem" class="profile-widget">
    <div style="position:relative;top:-40px;left:5px;text-align:left;" id="uploadPicLinkDiv">`+uploadPicLink+`</div>
    <div class="widget widget-chart-one mb-3 profile-widget">
    `+profileMastery+`
    </div>
    <div class="widget widget-chart-one mb-3 profile-widget" id="profileSlayerDiv">
    `+profileSlayer+`
    </div>
    </div>
    </div>
    `

    if (isplayerpp == "yes"){
        document.querySelector("#isppspan").innerHTML = `<tr><td width="100%" style="padding-top: 2px; padding-bottom: 2px; padding-left: 2px;"><b><font size="1"><font color="#E79A31">PREFERRED PLAYER</font></b></td></tr>`
    };


    const classCrest = profileCrests.match(/left:9px.*\n(.*)/i)
    const ferocityCrest = profileCrests.match(/left:83px.*\n(.*)/i)
    const preservationCrest = profileCrests.match(/left:157px.*\n(.*)/i)
    const afflictionCrest = profileCrests.match(/left:231px.*\n(.*)/i)
    if (classCrest){
        document.querySelector("#classCrestDiv").innerHTML = classCrest[1]
    }
    if (ferocityCrest){
        document.querySelector("#ferocityCrestDiv").innerHTML = ferocityCrest[1]
    }
    if (preservationCrest){
        document.querySelector("#preservationCrestDiv").innerHTML = preservationCrest[1]
    }
    if (afflictionCrest){
        document.querySelector("#afflictionCrestDiv").innerHTML = afflictionCrest[1]
    }


    const allPotionsInfo = await info("All Potions");
    const allPotions = allPotionsInfo.map(([item]) => item);
    const activePotions = (profileSkills.match(/alt="([^"]*)"/g) || []).map(match => match.slice(5, -1).replace(/'/g,''));
    const missingPotions = allPotions.filter(item => !activePotions.includes(item));
    const missingString = missingPotions.map((item, index) => (index > 0 && index % 2 === 0) ? `<br>${item}` : item).join(', ').replace(/'/g,'');
    document.querySelector("#missing").innerHTML = `<a id="missingPotions" onmouseout="kill()"><img src="https://studiomoxxi.com/moxximod/bot.png" id="missingRobot"></a>`

    if (GM_getValue("auth").match("Full")){
        document.querySelector("#missingPotions").setAttribute("onmouseover", `statspopup(event,'<b>Missing ${missingPotions.length} Potions</b><p>${missingString}')`);
    } else {
        document.querySelector("#missingPotions").setAttribute("onmouseover", `statspopup(event,'<b>Missing ${missingPotions.length} Potions</b><p>MoxxiMod+ subscribers can see a complete list of uncast potions here')`);
    };

    if (isplayerpp == "yes"){
        GM_addStyle (`
        #divHeaderName{color:#E79A31 !important;}
        .bg-danger,.bg-primary,.bg-secondary,.bg-success,.bg-warning{background-color:#E79A31 !important;}
        -moz-box-shadow: 0px 0px 3px 3px rgba(209,156,32,0.5);
        box-shadow: 0px 0px 3px 3px rgba(209,156,32,0.5);}
        #content > div > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > table > tbody > tr:nth-child(4) > td:nth-child(2) > b > font{color:#E79A31 !important;}
        #content > div > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > table > tbody > tr:nth-child(5) > td:nth-child(2) > b > font{color:#E79A31 !important;}
        #content > div > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > table > tbody > tr:nth-child(6) > td:nth-child(2) > b > font{color:#E79A31 !important;}
        #content > div > div:nth-child(1) > div:nth-child(1) > div:nth-child(2) > table > tbody > tr:nth-child(8) > td:nth-child(2) > b > font{color:#E79A31 !important;}
        `)
    };


    const faction = document.querySelector("body").innerHTML.match(/FACTION<\/font><\/b><\/td>[\n\r].*>(.*?) \((.*?)\)/i)
    const factionLvl = parseInt(faction[2])
    let factionImg;
    let profileFactionImg = []

    if (faction[1] == "Vordyn"){
        GM_addStyle (`.profile-widget{-webkit-box-shadow:0px 0px 3px 3px rgba(252,41,205,0.5);`)
        factionImg = 'https://studiomoxxi.com/moxxibots/factions/v.png'
    } else if (faction[1] == "Delruk"){
        GM_addStyle (`.profile-widget{-webkit-box-shadow:0px 0px 3px 3px rgba(255,120,39,0.5);`)
        factionImg = 'https://studiomoxxi.com/moxxibots/factions/d.png'
    } else if (faction[1] == "Alvar"){
        GM_addStyle (`.profile-widget{-webkit-box-shadow:0px 0px 3px 3px rgba(0,159,255,0.5);`)
        factionImg = 'https://studiomoxxi.com/moxxibots/factions/a.png'
    } else {
        GM_addStyle (`.profile-widget{-webkit-box-shadow:0px 0px 3px 3px rgba(26,26,26,1);`)
    };

    for (let i = 0; i < factionLvl; i++) {
        profileFactionImg.push(`<img src="`+factionImg+`" style="height:15%;width:15%;margin:2%;">`)
    };

    if (factionLvl >= 1){
        document.querySelector("#classLogo").setAttribute("onmouseover", `statspopup(event,'<b>${faction[1]}</b><br>Loyalty Level ${factionLvl}')`);
        document.querySelector("#classLogo").setAttribute("onmouseout", `kill()`);
    };

    document.querySelector("#classLogo").innerHTML = profileFactionImg.join('')


    const arrayOfItems = profileEq.match(/itempopup\(event,'[0-9]+'\)/g);
    getAugs(arrayOfItems);
    async function getAugs(arrayOfItems){
        let augs = []
        const itemLoop = async (item) => {
            const items = await superfetch(`item_rollover.php?id=${item.match(/[0-9]+/i)}`)
            const allAugs = items.match(/src="[^"]*" ONMOUSEOVER="itempopup\(event,'[0-9]+_[0-9]+'\)"/g)
            if (allAugs){
                for (let i = 0; i < allAugs.length; i++) {
                    augs.push(allAugs[i])
                };
            };
        };
        if (arrayOfItems){
            await Promise.all(arrayOfItems.map(itemLoop));
            document.querySelector("#allAugs").innerHTML = augs.sort().join('').replace(/src=/g,'<img src=').replace(/'\)"/g,`')" onmouseout="kill()">`)
        }
    };
};


async function menu(rgaName,charId,serverNo,profile,buyPointsLink){
    GM_addStyle (`#accordionExample{display:revert !important;background:#060818;}`)

    const crewId = (profile.toString().match(/<a href="\/crew_profile\?id=([0-9]+)">/i) || [false,false])[1]
    const level = parseInt(document.querySelector('.toolbar_level').innerHTML)

    document.querySelector("#accordionExample").innerHTML = `
    <li class="menu">
    <a href="#rga" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
    <div><span> MY RGA</span></div>
    <div><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg></div>
    </a>
    <ul class="collapse submenu list-unstyled" id="rga" data-parent="#accordionExample">
    <input type="text" id="rg_sess_id" value="${rgaName}" class="form-control-new" onclick="this.select();" style="margin-top:15px;margin-bottom:5px;height:20px !important;font-size:10px !important;width:80% !important">
    <li><a href="/myaccount">MY RGA</a></li>
    <li><a href="/accountinfo">MY ACCOUNT</a></li>
    <li><a href="/user_preferences">PREFERENCES</a></li>
    <li><a href="?cmd=logout">LOGOUT</a></li>
    </ul>
    </li>

    <li class="menu">
    <a href="/home" class="dropdown-toggle">
    <div><span> HOME</span></div>
    </a>
    </li>

    <li class="menu" id="character">
    <a href="#components" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
    <div><span> CHARACTER</span></div>
    <div><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg></div>
    </a>
    <ul class="collapse submenu list-unstyled" id="components" data-parent="#accordionExample">
    <li><a href="/profile">PROFILE</a></li>
    <li><a href="/ow_messagecenter">MESSAGES</a></li>
    <li><a href="/cast_skills">SKILLS</a></li>
    <li><a href="/allies">MY ALLIES</a></li>
    <li><a href="/underlings">UNDERLINGS</a></li>
    <li><a href="https://rampidgaming.outwar.com/ppoverview_s2?owsrv=${serverNo}&owchar=${charId}&rg_sess_id=${rgaName}" TARGET="BLANK">PREF PLAYER</a></li>
    </ul>
    </li>

    <li class="menu" id="economy">
    <a href="#elements" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
    <div><span> ECONOMY</span></div>
    <div><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg></div>
    </a>
    <ul class="collapse submenu list-unstyled" id="elements" data-parent="#accordionExample">
    <li><a href="/treasury?type=-1">BUY ITEMS</a></li>
    <li><a href="/mytreasury">SELL ITEMS</a></li>
    <li><a href="/supplies">SUPPLIES</a></li>
    <li><a href="/pointtransfer">TRANSFER PNTS</a></li>
    <li><a TARGET="_blank" href="${buyPointsLink}"> BUY POINTS</a></li>
    </ul>
    </li>

    <li class="menu">
    <a href="#datatables" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
    <div><span> SERVER</span></div>
    <div><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg></div>
    </a>
    <ul class="collapse submenu list-unstyled" id="datatables" data-parent="#accordionExample">
    <li><a href="/attack_search">SEARCH</a></li>
    <li><a href="/newrankings">RANKINGS</a></li>
    <li><a href="/gladiator">GLADIATORS</a></li>
    <li><a href="/event?eventid=woz">WAR OF ZHUL</a></li>
    <li><a href="/event?eventid=top">TRIAL OF POWER</a></li>
    </ul>
    </li>

    <li class="menu">
    <a href="#menuCrew" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
    <div><span> CREW</span></div>
    <div><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg></div>
    </a>
    <ul class="collapse submenu list-unstyled" id="menuCrew" data-parent="#accordionExample">
    </ul>
    </li>

    <li class="menu">
    <a href="#pvp" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
    <div><span> PVP</span></div>
    <div><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg></div>
    </a>
    <ul class="collapse submenu list-unstyled" id="pvp" data-parent="#accordionExample">
    <li><a href="/attacklog">ATTACK LOG</a></li>
    <li><a href="/pvptourney">OPEN TOURNEY</a></li>
    <li><a href="/closedpvp">PVP BRAWL</a></li>
    <li><a href="/bounty">BOUNTY BOARD</a></li>
    <li><a href="/crew_hitlist">CREW HITLIST</a></li>
    <li><a href="/myhitlist">MY HITLIST</a></li>
    </ul>
    </li>

    <li class="menu">
    <a href="#items" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
    <div><span> ITEMS</span></div>
    <div><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg></div>
    </a>
    <ul class="collapse submenu list-unstyled" id="items" data-parent="#accordionExample">
    <li><a href="/vault">VAULT</a></li>
    <li><a href="/blacksmith">BLACKSMITH</a></li>
    <li><a href="/augmentequip">ADD AUGMENTS</a></li>
    <li><a href="/itemtransfer">ITEM TRANSFER</a></li>
    <li><a href="/dungeons">DUNGEONS</a></li>
    <li><a href="/cauldron">CAULDRON</a></li>
    <li><a href="/kotw">KOTW</a></li>
    </ul>
    </li>

    <li class="menu">
    <a href="#quests" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
    <div><span> QUESTS</span></div>
    <div><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg></div>
    </a>
    <ul class="collapse submenu list-unstyled" id="quests" data-parent="#accordionExample">
    <li><a href="/weeklyquests">BOOSTERS</a></li>
    <li><a href="/questlog">QUEST LOG</a></li>
    <li><a href="/collections">COLLECTIONS</a></li>
    <li><a href="/challenge">CHALLENGES</a></li>
    </ul>
    </li>

    <li class="menu">
    <a href="/world" class="dropdown-toggle">
    <div><span> WORLD</span></div>
    </a>
    </li>
    `

    var ulElement = document.getElementById("menuCrew");
    if (crewId){
        var liHome = document.createElement("li");
        var liProfile = document.createElement("li");
        var liRaids = document.createElement("li");
        var liBosses = document.createElement("li");
        var liVault = document.createElement("li");
        var liGods = document.createElement("li");
        var liLeave = document.createElement("li");
        liHome.innerHTML = `<a href="/crew_home">CREW HOME</a>`
        liProfile.innerHTML = `<a href="/crew_profile">CREW PROFILE</a>`
        liRaids.innerHTML = `<a href="/crew_raidresults.php?crewid=${crewId}&moxximod">RAID RESULTS</a>`
        liBosses.innerHTML = `<a href="/crew_bossspawns">RAID BOSSES</a>`
        liVault.innerHTML = `<a href="/crew_vault">CREW VAULT</a>`
        liGods.innerHTML = `<a href="/godstatus">GOD STATUS</a>`
        liLeave.innerHTML = `<a href="/crew_leavecrew">LEAVE CREW</a>`
        ulElement.appendChild(liHome);
        ulElement.appendChild(liProfile);
        ulElement.appendChild(liRaids);
        ulElement.appendChild(liBosses);
        ulElement.appendChild(liVault);
        ulElement.appendChild(liGods);
        ulElement.appendChild(liLeave);
    } else {
        var liInvites = document.createElement("li");
        liInvites.innerHTML = `<a href="/crewinvites">CREW INVITES</a>`
        ulElement.appendChild(liInvites);
    };
    if (level >= 91){
        const ulElement = document.querySelector("#components");
        const newLiElement = document.createElement("li");
        newLiElement.innerHTML = `<a href="/changefaction">FACTIONS</a>`;
        ulElement.appendChild(newLiElement);
    };
};


async function challengeStatus(server){
    const data = await superfetch(`https://${server}.outwar.com/ajax/challenge_status`);
    if (data.match('Trustees do not have access to this page')){
        data = `{"result":true,"tokens":"NA","p_tokens":"NA","timeleft":59210}`
    }
    return data;
}


async function toolbar(charId,toolbarData,dataTime,dataLevel,dataRage,dataExp,dataEnhancementExp,dataToLevel,dataGrowth,dataMinimum,dataExpPerTurn,dataRagePerTurn,dataMaximum,dataGold,dataPoints,dataPremium,dataSkillPoints,dataFreeTokens,dataPremiumTokens,dataAttack,dataHp,dataCritical,dataRampage,dataBlock){
    GM_addStyle (`body > center > div.sub-header-container{display:revert !important;}`)

    document.querySelector("body > center > div.sub-header-container > header > a").remove()

    const toolbarDivcount = document.querySelectorAll("li.nav-item.more-dropdown.little-space.hide-on-mob").length
    for (let i = 3; i < toolbarDivcount+3; i++) {
        document.querySelector("li.nav-item.more-dropdown.little-space.hide-on-mob:nth-child("+i+")").setAttribute("style","display:none")
    };

    const toolbarNewLi = document.createElement('li');
    toolbarNewLi.innerHTML = `
    <span id="toolbarCharacters" class="toolbarSpan"></span>
    <span id="toolbarRgas" class="toolbarSpan"></span>
    <span id="toolbarPoints" class="toolbarSpan"></span>
    <span id="toolbarClock" class="toolbarSpan"></span>
    <span id="toolbarLvl" class="toolbarSpan"></span>
    <span id="toolbarRage" class="toolbarSpan"></span>
    <span id="toolbarTiles" class="toolbarSpan"><img src="https://studiomoxxi.com/moxximod/loading-gif.gif"></span>
    `;
    toolbarNewLi.setAttribute('class','nav-item more-dropdown little-space hide-on-mob')
    const toolbarUl = document.querySelector("body > center > div.sub-header-container > header > ul.navbar-nav.flex-row.mr-auto.toolbar-nav");
    toolbarUl.appendChild(toolbarNewLi);

    if (document.URL.match("home") && !document.URL.match("crew_home")) {
        document.querySelector("#toolbarTiles").remove();
    };

    const utcDate = new Date();
    const estOffset = 5 * 60;
    const estDate = new Date(utcDate.getTime() - estOffset * 60000);
    const estFormatter = new Intl.DateTimeFormat('en-US', {
        timeZone: 'UTC',
        weekday: 'long'
    });
    const dayOfTheWeek = estFormatter.format(estDate);

    const untilMax = Math.ceil((dataMaximum - dataRage) / dataRagePerTurn);
    const maxTime = (parseInt(dataTime.match(/([0-9]+):/i)[1]) + untilMax) % 12;
    const maxHour = (untilMax > 0) ? `${maxTime}:00` : "NOW";

    if (GM_getValue('charId') != charId && parseInt(dataLevel) >= 80){
        const qbp = await superfetch('ajax/backpackcontents.php?tab=quest');
        const reps = qbp.match(/data-name="Badge Reputation"/i) ? parseInt(qbp.match(/data-name="Badge Reputation" data-itemqty="([0-9]+)"/i)[1]) : 0;
        GM_setValue('charId', charId);
        GM_setValue('badgeReps', reps);
    };
    const dataReps = GM_getValue('badgeReps') ? GM_getValue('badgeReps') : 0

    const pointsTable = `<table class=pop><tr><td><b>PB POINTS:</td><td>${dataPoints.toLocaleString()}</td></tr><tr><td><b>PREM POINTS:</td><td>${dataPremium.toLocaleString()}</td></tr><tr><td><b>FREE TOKENS:</td><td>${dataFreeTokens.toLocaleString()}</td></tr><tr><td><b>PREM TOKENS:</td><td>${dataPremiumTokens.toLocaleString()}</td></tr><tr><td><b>GOLD:</td><td>${dataGold.toLocaleString()}</td></tr><tr><td><b>SKILL POINTS:</td><td>${dataSkillPoints.toLocaleString()}</td></tr><tr><td><b>BADGE REPS:</td><td>${dataReps}</td></tr></table>`
    const expTable = `<table class=pop><tr><td><b>EXPERIENCE:</td><td>${dataExp.toLocaleString()}</td></tr><tr><td><b>ENHANCEMENT EXP:</td><td>${dataEnhancementExp.toLocaleString()}</td></tr><tr><td><b>NEEDED TO LEVEL:</td><td>${dataToLevel}</td></tr><tr><td><b>GROWTH TODAY:</td><td>${dataGrowth.toLocaleString()}</td></tr><tr><td><b>MINIMUM EXP:</td><td>${dataMinimum.toLocaleString()}</td></tr><tr><td><b>PER TURN:</td><td>${dataExpPerTurn.toLocaleString()}</td></tr></table>`
    const rageTable = `<table class=pop><tr><td><b>MAXIMUM:</td><td>${dataMaximum.toLocaleString()}</td></tr><tr><td><b>WILL MAX:</td><td>${maxHour}</td></tr><tr><td><b>PER TURN:</td><td>${dataRagePerTurn.toLocaleString()}</td></tr><tr><td><b>ATTACK:</td><td>${dataAttack.toLocaleString()}</td></tr><tr><td><b>HIT POINTS:</td><td>${dataHp.toLocaleString()}</td></tr><tr><td><b>CRITICAL:</td><td>${dataCritical.toLocaleString()}%</td></tr><tr><td><b>RAMPAGE:</td><td>${dataRampage.toLocaleString()}%</td></tr><tr><td><b>BLOCK:</td><td>${dataBlock.toLocaleString()}%</td></tr></table>`

    if (GM_getValue("savedRgas") == undefined) {GM_setValue("savedRgas","no sessions saved")}
    if (GM_getValue("savedRgas") == "no sessions saved"){
        document.querySelector("#toolbarRgas").remove()
    } else {

        const options = GM_getValue("savedRgas")
        document.querySelector("#toolbarRgas").innerHTML = `
        <select id="dropdownRgas" class="form-control-new">
        <option>My RGAs</option>
        ${options}
        </select>
        `

        document.getElementById("dropdownRgas").addEventListener("change", function() {
            var selectedValue = this.value;
            if (selectedValue !== "") {
                window.location.href = selectedValue;
            };
        });
    };

    document.querySelector("#toolbarPoints").innerHTML = `<a onmouseover="statspopup(event,'${pointsTable}')" onmouseout="kill()" class="form-control-new">$</a>`

    document.querySelector("#toolbarClock").innerHTML = `<a onmouseover="statspopup(event,'<table class=pop><tr><td><b>${dayOfTheWeek.toUpperCase()}</td></tr></table>')" onmouseout="kill()" class="form-control-new">${dataTime}</a>`

    document.querySelector("#toolbarLvl").innerHTML = `<a onmouseover="statspopup(event,'${expTable}')" onmouseout="kill()" class="form-control-new">LEVEL: ${dataLevel}</a>`

    document.querySelector("#toolbarRage").innerHTML = `<a onmouseover="statspopup(event,'${rageTable}')" onmouseout="kill()" class="form-control-new" id="toolbarRageText">RAGE: ${dataRage.toLocaleString()}</a>`

    if (toolbarData.match(`<span style="color:#00CC00">`)){ document.querySelector("#toolbarRageText").setAttribute("style","border: 2px SOLID #FF0000 !important") };

    if (dataFreeTokens == 30){ document.querySelector("#toolbarPoints a").setAttribute("style","border: 2px SOLID #F9E400 !important") };

    if (dataReps >= 15){ document.querySelector("#toolbarPoints a").setAttribute("style","border: 2px SOLID #00FF00 !important") };

    if (dataToLevel.match(/LEVEL!/)){ document.querySelector("#toolbarLvl a").setAttribute("style","border: 2px SOLID #00FF00 !important") };

    document.querySelector("#language-dropdown > svg").outerHTML = `<a class="form-control-new"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg></a>`

    const dropdownNative = document.querySelector("body > center > div.sub-header-container > header > ul.navbar-nav.flex-row.mr-auto.toolbar-nav > li:nth-child(1)").innerHTML
    const dropdownModified = dropdownNative.replace(`<div class="dropdown  custom-dropdown-icon">`,'').replace(`<select id="charselectdropdown" style="" data-select2-id="select2-data-charselectdropdown" tabindex="-1" class="select2-hidden-accessible" aria-hidden="true">`,'').replace(`</div>`,'').replace(/<\/optgroup><\/select>.*[\n\r].*[\n\r].*/i,`</optgroup></select>`).replace(`<option value="0">--Change Server--</option>`,'')
    document.querySelector("#toolbarCharacters").innerHTML = `<select id="dropdownCharacters" class="form-control-new">${dropdownModified}</select>`
    document.getElementById('dropdownCharacters').addEventListener('change', function() {
        let sticky = window.location.href.split('.com')[1].replace(/rg_sess_id=[A-Za-z0-9]+&suid=[0-9]+&serverid=[0-9]+&/i,'').replace(/\?suid=[0-9]+/i,'').replace(/&serverid=[0-9]+/i,'');
        const symbol = sticky.match(/\?/i) ? '&' : "?"
        if (sticky == "changefaction"){
            sticky = "home"
        };
        const dropdown = document.getElementById("dropdownCharacters");
        const selectedOption = dropdown.options[dropdown.selectedIndex];
        const characterId = selectedOption.value;
        window.location.href = `${sticky}${symbol}suid=${characterId}`;
    });

    const raidForming = document.body.innerHTML.match('images/toolbar/NewRaid.png')
    const newMessage = document.body.innerHTML.match(/img border="0" src="http:\/\/[A-Za-z]+\.outwar\.com\/images\/toolbar\/Message\.png"/i)
    const toolbarButtons = document.querySelector("body > center > div.sub-header-container > header > ul.navbar-item.flex-row.ml-auto")
    toolbarButtons.innerHTML = `
    <li class="toolbarButtons"><a href="javascript:void(0);" id="btnTravel" onmouseover="statspopup(event,'<b>Fast travel<b>')" onmouseout="kill()"><img src="https://studiomoxxi.com/moxximod/fasttravel.png" height="25px" width="25px"></a></li>
    <li class="toolbarButtons" id="btnAppsLi"><a href="javascript:void(0);" id="btnApps" onmouseover="statspopup(event,'<b>MoxxiMod apps<b>')" onmouseout="kill()"><img src="https://studiomoxxi.com/moxximod/toolbarbot.png" id="toolbarbot" height="25px" width="25px"></a></li>
    <li class="toolbarButtons"><a href="javascript:void(0);" id="btnCaster" onmouseover="statspopup(event,'<b>Caster<b>')" onmouseout="kill()"><img src="https://studiomoxxi.com/moxximod/castericon.webp" height="25px" width="25px"></a></li>
    <li class="toolbarButtons"><a href="javascript:void(0);" id="btnSearch" onmouseover="statspopup(event,'<b>Search<b>')" onmouseout="kill()"><img src="https://studiomoxxi.com/moxximod/searchicon.webp" height="25px" width="25px"></a></li>
    <li class="toolbarButtons"><a href="javascript:void(0);" onclick="toggleEquipment();" onmouseover="statspopup(event,'<b>Equipment<b>')" onmouseout="kill()"><img src="https://studiomoxxi.com/moxximod/toolbareq.png"></a></li>
    <li class="toolbarButtons"><a onclick="toggleBackpack(null,${charId});" href="javascript:void(0);" onmouseover="statspopup(event,'<b>Backpack<b>')" onmouseout="kill()"><img src="https://studiomoxxi.com/moxximod/toolbarbp.png" style="margin-right:1rem;"></a></li>
    `
    if (raidForming){
        const raidFormingLi = document.createElement("li");
        raidFormingLi.classList.add('toolbarButtons');
        raidFormingLi.innerHTML = `<a href="crew_raidsforming"><img src="https://studiomoxxi.com/moxximod/NewRaid.png" onmouseover="statspopup(event,'<b>Raid forming</b>')" onmouseout="kill()" height="25px" width="25px"></a>`
        toolbarButtons.insertBefore(raidFormingLi,toolbarButtons.firstChild)
    };
    if (newMessage){
        const newMessageLi = document.createElement("li");
        newMessageLi.classList.add('toolbarButtons');
        newMessageLi.innerHTML = `<a href="ow_messagecenter"><img src="https://studiomoxxi.com/moxximod/messages.png" onmouseover="statspopup(event,'<b>New Messages</b>')" onmouseout="kill()" height="25px" width="25px"></a>`
        toolbarButtons.insertBefore(newMessageLi,toolbarButtons.firstChild)
    };

    document.querySelector("#btnTravel").addEventListener("click", travelMenuOpen);
    document.querySelector("#btnApps").addEventListener("click", appsMenuOpen);
    document.querySelector("#btnCaster").addEventListener("click", casterMenuOpen);
    document.querySelector("#btnSearch").addEventListener("click", searchMenuOpen);
};


async function tiles(profile){

    const endpoints = ['myaccount','gladiator','raidtools','crew_bossspawns','supplies','event?eventid=top','event?eventid=woz','ajax_changeroomb'];
    const responses = await Promise.all(endpoints.map(endpoint => superfetch(endpoint)));

    if (responses[1] == "error"){
        return;
    };

    let tiles = [];
    const now = Math.round(new Date().getTime())

    const rgaTrade = responses[0].match(/<a href="trade\?suid=([0-9]+)&serverid=[0-9]+"><img border="0" height="13" src="[^"]*" alt="Trade">/i)
    if (rgaTrade){
        tiles.push(`<a href="trade?suid=${rgaTrade[1]}"><img class="tile-still" src="https://studiomoxxi.com/moxximod/trade.png" onmouseover="statspopup(event,'Pending trade')" onmouseout="kill()"></a>`)
    };
    const crewTrade = responses[0].match(/a href="\/trade\?isCrewTrade=1"/i)
    if (crewTrade){
        tiles.push(`<a href="trade?isCrewTrade=1"><img class="tile-still" src="https://studiomoxxi.com/moxximod/tradecrew.png" onmouseover="statspopup(event,'Pending crew trade')" onmouseout="kill()"></a>`)
    };

    const parseData = new DOMParser();
    const gladiator = parseData.parseFromString(responses[1], 'text/html');
    const divs = gladiator.querySelectorAll('.divQuest');
    for (var g = 0; g < divs.length; g++){
        const divContent = divs[g].innerHTML
        if (divContent.match('Will retreat in')){
            const gladInfo = divContent.match(/<\/div> <div class="divQuestMob"> <a href="[^"]*"><img onmouseover="popup\(event,'Find (.*?)!',1\);" onmouseout="kill\(\);" src="([^"]*)"><\/a>/i)
            const gladLink = divContent.match(/<a href="(gladiator\?mobid=[0-9]+")>/i)[1]
            const gladName = gladInfo[1]
            const gladImg = gladInfo[2]
            const godHtmlId = gladName.replace(/ /g,'').replace(/,/g,'')
            const retreatsIn = parseInt(divContent.match(/countdown = ([0-9]+)/i)[1])*1000
            const timeRemaining = Math.ceil((retreatsIn-now)/(3.6e+6))
            let classEffect;
            if (timeRemaining <= 24){
                classEffect = "tile-animate"
            } else {
                classEffect = "tile-still"
            };
            tiles.push(`<a href="${gladLink}"><img onmouseout="kill()" onmouseover="statspopup(event,'<b>${gladName}</b><br>Retreats in ${timeRemaining} hours')" src="${gladImg}" class="${classEffect}" id="${godHtmlId}"></a>`)
        };
    };

    if (responses[2].match("Teleport to")) {
        const gods = responses[2].match(/<img height="200" width="200" src="[^"]*" border="0" \/><\/a><br\/>[\n\r].*[\n\r].*[\n\r].*? <\/font><\/strong><\/a><br\/><br\/>/g)
        for (var i = 0; i < gods.length; i++){
            const godImg = gods[i].match(/<img height="200" width="200" src="([^"]*)" border="0" \/>/i)[1]
            const godName = gods[i].match(/(.*?) <\/font><\/strong><\/a><br\/><br\/>/i)[1]
            tiles.push(`<img onmouseout="kill()" onmouseover="statspopup(event,'<b>God spawned!</b><br>${godName}')" src="${godImg}" class="tile-animate">`)
        };
    };
    if (profile.match(/<br \/>Noxious Slug has been spotted!<br>/i)){
        tiles.push(`<img onmouseout="kill()" onmouseover="statspopup(event,'<b>God spawned!</b><br>Noxious Slug')" src="images/mobs/noxSlug.jpg" class="tile-animate">`)
    };
    if (profile.match(/<br \/>Beast of Cards has been spotted!<br>/i)){
        tiles.push(`<img onmouseout="kill()" onmouseover="statspopup(event,'<b>God spawned!</b><br>Beast of Cards')" src="images/mobs/cardBeast.jpg" class="tile-animate">`)
    };

    if ((GM_getValue("untilbrawl") == undefined && GM_getValue("brawlends") == undefined) || (GM_getValue("untilbrawl") <= now || GM_getValue("brawlends") <= now)){
        const closedPvp = await superfetch('closedpvp');
        const countdownBrawl = parseInt(closedPvp.match(/var countdown = ([0-9]+)/i)[1])*1000
        if (closedPvp.match('Brawl ends in')){
            GM_setValue("brawlends",countdownBrawl);
            GM_deleteValue("untilbrawl");
        } else {
            GM_setValue("untilbrawl",countdownBrawl);
            GM_deleteValue("brawlends");
        };
    };
    let brawlMsg; let brawlTimer; let brawlStyle;
    if (GM_getValue("untilbrawl") >= now){
        brawlMsg = "Brawl starts in"
        brawlTimer = GM_getValue("untilbrawl");
        brawlStyle = 'filter:grayscale(100%);'
    } else {
        brawlMsg = "Brawl ends in"
        brawlTimer = GM_getValue("brawlends");
        brawlStyle = ''
    };
    const differenceBrawl = (brawlTimer-now)/(3.6e+6)
    if (differenceBrawl <= 72){
        tiles.push(`<a href="closedpvp"><img class="tile-still" src="https://studiomoxxi.com/moxximod/brawlicon.webp" onmouseover="statspopup(event,'${brawlMsg} ${Math.ceil(differenceBrawl)} hours')" onmouseout="kill()" style="${brawlStyle}"></a>`)
    };

    const bosses = responses[3].match(/<a href="formraid\.php\?target=[0-9]+" ONMOUSEOVER="popup\(event,'[^']*'\)" ; ONMOUSEOUT="kill\(\)"><img src="[^"]*" width="166" height="166" border="0" style="border-radius: 10%;"><\/a>[\n\r].*[\n\r].*[\n\r].*[\n\r].*[\n\r].*/g)
    if (bosses){
        for (let i = 0; i <= bosses.length-1; i++) {
            const boss = bosses[i]
            const bossName = boss.match(/<h[0-9]+ class="card-user_name">(.*?)<\/h3>/i)[1]
            const bossHealth = boss.match(/<p class="card-user_occupation"> ([0-9]+)%/i)[1]
            const bossImg = boss.match(/src="([^"]*)"/i)[1]
            const bossId = boss.match(/boss_stats\.php\?spawnid=([0-9]+)/i)[1]
            let classEffect;
            if (bossHealth <= 10){
                classEffect = "tile-animate"
            } else {
                classEffect = "tile-still"
            };
            tiles.push(`<a href="boss_stats.php?spawnid=${bossId}"><img class="${classEffect}" src="${bossImg}" onmouseover="statspopup(event,'<b>${bossName}</b><br>Health: ${bossHealth}%<br>(click for stats)')" onmouseout="kill()"></a>`)
        };
    };

    const supplies = parseInt(responses[4].match(/<img border="0" src="images\/suppliestriangle\.gif" width="11" height="11">[\n\r](.*)%<\/td>/i)[1]);
    if (supplies < 100){
        tiles.push(`<a href="javascript:void(0);" id="maxSupplies"><img src="https://studiomoxxi.com/moxximod/supplies.png" class="tile-still" onmouseover="popup(event,'<b>Supplies: ${supplies}%</b><br>(Click to max)')" onmouseout="kill()"></a>`)
    };

    const strength = parseInt(document.body.innerHTML.match(/'Strength: ([0-9]+)'/i)[1])
    if (strength < 100){
        tiles.push(`<img src="https://studiomoxxi.com/moxximod/strength.png" class="tile-still" onmouseover="popup(event,'<b>Strength: ${strength}%</b>')" onmouseout="kill()"></a>`)
    };

    const countdownTOP = parseInt(responses[5].match(/var countdown = ([0-9]+)/i)[1])*1000
    const differenceTOP = (countdownTOP-now)/(3.6e+6)
    if (differenceTOP <= 336){
        tiles.push(`<a href="event?eventid=top"><img class="tile-still" src="https://studiomoxxi.com/moxximod/top.png" onmouseover="statspopup(event,'<b>Trial of Power</b><br>${Math.ceil(differenceTOP)} hours</b>')" onmouseout="kill()"></a>`)
    };

    const countdownWOZ = parseInt(responses[6].match(/var countdown = ([0-9]+)/i)[1])*1000
    const differenceWOZ = (countdownWOZ-now)/(3.6e+6)
    if (differenceWOZ <= 336){
        tiles.push(`<a href="event?eventid=woz"><img class="tile-still" src="https://studiomoxxi.com/moxximod/top.png" onmouseover="statspopup(event,'<b>War of Zhul</b><br>${Math.ceil(differenceWOZ)} hours</b>')" onmouseout="kill()"></a>`)
    };

    if (responses[7].replace(/"nft":"[^"]*",/i,'').match(/"isDead":true,"type":1/i)){
        const godName = responses[7].replace(/"nft":"[^"]*",/i,'').match(/\{"name":"([^"]*)","level":"[0-9]+","rage":"[0-9]+","h":"[^"]*","encid":"[^"]*","mobId":"[0-9]+","spawnId":"[0-9]+","image":"[^"]*","isDead":true,"type":1/i)[1]
        const godsFetch = await superfetch('godstatus');
        const gods = godsFetch.match(/<a href="raidattack\.php\?raidid=[0-9]+">.*?<\/a>/g).join(' ');
        if (!gods.match(godName)){
            tiles.push(`<a href="world"><img src="https://studiomoxxi.com/moxximod/camp.webp" class="tile-still" onmouseover="popup(event,'<b>${godName}</b><br>Camp detected')" onmouseout="kill()"></a>`)
        };
    };

    const crewId = (profile.toString().match(/<a href="\/crew_profile\?id=([0-9]+)">/i) || [false,false])[1]
    if (crewId){
        const raidResults = await fetch(`crew_raidresults.php?all_results=Display+all+raid+results&crewid=${crewId}`).then(res => res.text());
        const resultsMatch = raidResults.match(/<td align="left" valign="top">(.*?)<\/td>[\n\r]<td align="left" valign="top"> <font color="[^"]*"><b>(.*?)<\/b><\/font><\/td>[\n\r]<td align="left" valign="top"><a href="raidattack\.php\?raidid=([0-9]+)">View<\/a><\/td>/i);
        if (resultsMatch){
            const raidName = resultsMatch[1]
            const raidResult = resultsMatch[2]
            const raidId = resultsMatch[3]
            const raidPage = await fetch(`raidattack.php?raidid=${raidId}`).then(res => res.text());
            const raidImg = raidPage.match(/<div class="[^"]*">[\n\r]<img src="([^"]*)">[\n\r]<\/div>/i)[1];
            tiles.push(`<a href="raidattack.php?raidid=${raidId}"><img class="tile-still" src="${raidImg}" onmouseover="statspopup(event,'<b>${raidResult} vs.</b><br>${raidName}')" onmouseout="kill()" style="filter:grayscale(100%);"></a>`);
        };
    };

    var checkElementInterval = setInterval(function() {
        var targetElement = document.querySelector("body > center > div.sub-header-container > header");
        if (targetElement) {

            if (!document.URL.match("home") || document.URL.match("crew_home")) {
                document.querySelector("#toolbarTiles").innerHTML = tiles.join(' ');
            };

            if (document.querySelector("#maxSupplies")){
                document.querySelector("#maxSupplies").addEventListener("click", maxSupplies);
            };

            clearInterval(checkElementInterval);
        };
    }, 500);

    if (document.URL.match("home") && !document.URL.match("crew_home") && !document.URL.match("homepost")) {
        document.querySelector("#homeTilesContainer").innerHTML = tiles.join(' ')
    } else {
        return tiles;
    };
};


async function maxSupplies(){
    fetch('supplies', {
        method: 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        body: new URLSearchParams({'buymax': 'Buy Max',})})
    GM_addStyle (`#maxSupplies{display:none !important;`)
};


async function travelMenuOpen() {
    casterMenuClose();
    appsMenuClose();
    searchMenuClose();

    let serverNo;
    let server;
    if (window.location.toString().match('sigil')){
        serverNo = 1
        server = 'sigil'
    };
    if (window.location.toString().match('torax')){
        serverNo = 2
        server = 'torax'
    };
    const rgaName = document.querySelector("#rg_sess_id").value;
    const charId = document.body.innerHTML.match(/outwar\.com\/page\?x=([0-9]+)/i)[1];

    document.querySelector("#btnTravel > img").classList.toggle('rotate180');
    GM_addStyle (`#btnTravel > img {transition: transform 0.5s ease;}`)
    GM_addStyle (`.rotate180 {transform: rotate(180deg);}`)

    document.querySelector("#btnTravel").removeEventListener("click", travelMenuOpen);
    document.querySelector("#btnTravel").addEventListener("click", travelMenuClose)
    if (travelMenuCreated == false){

        const fastTravelHtml = `
        <input style="width:300px;" id="travelRoomNum" type="text" placeholder="ENTER ROOM #" class="form-control-new travel-destination plus-destination" autocomplete="off">
        <a href="javascript:void(0);" class="form-control-new travel-destination plus-destination"><img alt="36195" class="travel-img" src="images/mobs/mobl7.jpg">AEZEL, GARDEN MANIC</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination travel-teleporter"><img alt="Astral Ward" class="travel-img" src="images/items/saveitem2.jpg">ASTRAL RIFT</a></a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination travel-teleporter"><img alt="Astral Teleporter" class="travel-img" src="images/items/astralteleporter.png">ASTRAL RUINS</a><br>
        <a href="world.php?room=25989" class="form-control-new travel-destination"><img class="travel-img" src="images/rooms/tile_chaltoken.jpg">CHALLENGE ARENA</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination plus-destination"><img alt="32877" class="travel-img" src="images/mobs/chaosgolem4.jpg">CHAOS GOLEMS</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination travel-teleporter"><img alt="Sanctum Key" class="travel-img" src="images/rooms/tile_badge.jpg">CITY SANCTUM</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination plus-destination"><img alt="26201" class="travel-img" src="images/mobs/runenpc4.jpg">ELEMENTAL OVERLORD</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination plus-destination"><img alt="50" class="travel-img" src="images/rooms/tile_glad1.png">GLADIATOR ARENA</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination plus-destination"><img alt="28040" class="travel-img" src="images/rooms/tile_infinity.png">INFINITE TOWER</a><br>
        <a href="world.php?room=11" class="form-control-new travel-destination"><img class="travel-img" src="images/4way.jpg">INTERSECTION ROOM 11</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination plus-destination"><img alt="28123" class="travel-img" src="images/mobs/mobm91.jpg">PRISON: HOVOK</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination travel-teleporter"><img alt="Grove Insignia" class="travel-img" src="images/rooms/tile_tgrove.png">TWILIGHT GROVE</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination travel-teleporter"><img alt="Triworld Teleporter" class="travel-img" src="images/rooms/tile_doorts2.png">TRIWORLD SANCTUARY</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination plus-destination"><img alt="42550" class="travel-img" src="images/rooms/tile_vault.png">VAULT OF MADNESS</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination travel-teleporter"><img alt="Veiled Teleporter" class="travel-img" src="images/items/veiledtp.png">VEILED PASSAGE</a><br>
        <a href="javascript:void(0);" class="form-control-new travel-destination travel-teleporter"><img alt="Veldara Teleporter" class="travel-img" src="images/items/veldarateleporter.jpg">VELDARA GARRISON</a>
        `

        var image = document.querySelector("#btnTravel").getBoundingClientRect();
        var newDiv = document.createElement('div');
        newDiv.id = 'travelDiv';
        newDiv.classList.toggle('widget');
        newDiv.innerHTML = fastTravelHtml;
        newDiv.style.position = 'absolute';
        newDiv.style.top = image.top + window.scrollY + 'px';
        newDiv.style.left = image.left + window.scrollX-320 + 'px';
        document.body.appendChild(newDiv);
    };

    if (!GM_getValue("auth").match("Full")){
        GM_addStyle (`a.plus-destination{opacity:0.25;}`)
        const plusOnly = document.querySelectorAll("a.plus-destination")
        for (let i = 0; i < plusOnly.length; i++) {
            plusOnly[i].innerHTML = `<img src="https://studiomoxxi.com/moxximod/toolbarbot.png" class="travel-img">MM+ REQUIRED`
        };
    };

    GM_addStyle (`#travelDiv {animation: moveAnimation 0.5s ease forwards;position:fixed;}`)
    GM_addStyle (`@keyframes moveAnimation {0% {width:370px;height:0px;position:fixed;top:0px;} 100% {width:370px;height:535px;position:fixed;top:45px;}}`)
    travelMenuCreated = true;

    document.querySelector("#travelRoomNum").addEventListener("keyup", async function(event) {
        if (event.keyCode === 13) {
            const roomNum = document.querySelector("#travelRoomNum").value
            await goToRoomNum(server,charId,roomNum)
        };
    });

    const travelTeleporterArray = document.querySelectorAll(".travel-teleporter");
    for (let i = 0; i < travelTeleporterArray.length; i++) {
        var teleporter = travelTeleporterArray[i];
        const keyName = teleporter.innerHTML.match(/alt="([^"]*)"/i)[1];
        teleporter.addEventListener("click", async function() {
            await activateKeyFromBp(server,rgaName,charId,serverNo,keyName);
            window.location.href = "world"
        });
    };
    const plusDestinationArray = document.querySelectorAll(".plus-destination");
    for (let i = 1; i < plusDestinationArray.length; i++) {
        var room = plusDestinationArray[i];
        const roomNum = room.innerHTML.match(/alt="([^"]*)"/i)[1];
        room.addEventListener("click", async function() {
            await goToRoomNum(server,charId,roomNum);
        });
    };
};


async function goToRoomNum(server,charId,roomNum){
    await loadingOverlay();
    await travelMenuClose();
    const send = await mmplus(`GoToRm|rganame|${server}|${charId}|${roomNum}`);
    if (send.match('Full')){


        async function endlessLoop() {
            const data = await superfetch('ajax_changeroomb.php',true);
            if (data.match(/"curRoom":"([0-9]+)"/i)[1] == roomNum) {
                window.location.href = "world"
                return;
            };
            setTimeout(endlessLoop, 250);
        };
        endlessLoop();
    } else {
        await loadingOff();
    };
};


async function activateKeyFromBp(server,rgaName,charId,serverNo,keyName){
    const kbp = await superfetch(`https://${server}.outwar.com/ajax/backpackcontents.php?rg_sess_id=${rgaName}&suid=${charId}&serverid=${serverNo}&tab=key`);
    if (!kbp.match(keyName)){
        alert('ERROR: You do not have the teleporter needed')
    } else {
        var regex = new RegExp(`data-name="${keyName}".*data-iid="([0-9]+)"`, 'i');
        const teleporter = new URLSearchParams({ 'action': 'activate', 'itemids[]': kbp.match(regex)[1] });
        await superpost(`https://${server}.outwar.com/ajax/backpack_action.php?rg_sess_id=${rgaName}&suid=${charId}&serverid=${serverNo}`,teleporter.toString());
    };
};


async function appsMenuOpen() {
    travelMenuClose();
    casterMenuClose();
    searchMenuClose();

    document.querySelector("#btnApps > img").classList.toggle('rotate180');
    GM_addStyle (`#btnApps > img {transition: transform 0.5s ease;}`)
    GM_addStyle (`.rotate180 {transform: rotate(180deg);}`)

    document.querySelector("#btnApps").removeEventListener("click", appsMenuOpen);
    document.querySelector("#btnApps").addEventListener("click", appsMenuClose);
    if (appsMenuCreated == false){

        const appsHtml = `
        <div class="appDiv" id="authApp"><img src="https://studiomoxxi.com/moxximod/authenticateicon.webp" class="app-img"><p>AUTHENTICATE</div>
        <div class="appDiv" id="moxxiVision"><img src="https://studiomoxxi.com/moxximod/sm%20icon.webp" class="app-img"><p>MOXXIVISION</div>
        <div class="appDiv" id="exportRga"><img src="https://studiomoxxi.com/moxximod/exporticon.webp" class="app-img"><p>EXPORT RGA</div>
        <div class="appDiv" id="itemStorage"><img src="https://studiomoxxi.com/moxximod/storageicon.png" class="app-img"><p>INVENTORY</div>
        <div class="appDiv" id="illusionsApp"><img src="https://studiomoxxi.com/moxximod/illusionicon.webp" class="app-img"><p>ILLUSIONS</div>
        <div class="appDiv" id="wildernessApp"><img src="https://studiomoxxi.com/moxximod/wildernessicon.webp" class="app-img"><p>WILDERNESS</div>
        <div class="appDiv" id="goToDiscord"><img src="https://studiomoxxi.com/moxximod/discordicon.png" class="app-img"><p>DISCORD</div>
        <div class="appDiv" id="themeApp"><img src="https://studiomoxxi.com/moxximod/themeicon.png" class="app-img"><p>OUTWAR THEME</div>
        <div class="appDiv plus-app" id="chaosTeles"><img src="https://studiomoxxi.com/moxximod/chaosteleicon.webp" class="app-img"><p>CHAOS TELES</div>
        <div class="appDiv plus-app" id="reportBadge"><img src="images/items/badge4d.png" class="app-img"><p>BADGE REPORT</div>
        <div class="appDiv plus-app" id="reportChaos"><img src="https://studiomoxxi.com/moxximod/chaosicon.webp" class="app-img"><p>CHAOS REPORT</div>
        <div class="appDiv plus-app" id="reportRune"><img src="https://studiomoxxi.com/moxximod/runeicon.webp" class="app-img"><p>RUNE REPORT</div>
        <div class="appDiv plus-app" id="reportEnhancer"><img src="https://studiomoxxi.com/moxximod/enhanceicon.webp" class="app-img"><p>ENHANCER REPORT</div>
        <div class="appDiv plus-app" id="reportLing"><img src="https://studiomoxxi.com/moxximod/lingicon.webp" class="app-img"><p>LING REPORT</div>
        <div class="appDiv plus-app" id="raidsReport"><img src="https://studiomoxxi.com/moxximod/raidreporticon.webp" class="app-img"><p>RAIDS REPORT</div>
        <div class="appDiv plus-app" id="savedRgas"><img src="https://studiomoxxi.com/moxximod/usersicon.png" class="app-img"><p>SAVED RGAS</div>
        <div class="appDiv plus-app" id="itemAnalyzer"><img src="https://studiomoxxi.com/moxximod/itemmanageicon.webp" class="app-img"><p>ITEM UPGRADES</div>
        <div class="appDiv plus-app" id="mobAttacker"><img src="landing/atkicon.png" class="app-img"><p>MOB ATTACKER</div>
        <div class="appDiv plus-app" id="mobRaider"><img src="landing/raidicon.png" class="app-img"><p>MOB RAIDER</div>
        <div class="appDiv plus-app" id="gladiatorApp"><img src="https://studiomoxxi.com/moxximod/gladicon.png" class="app-img"><p>GLADIATORS</div>
        `

        var image = document.querySelector("#btnApps").getBoundingClientRect();
        var newDiv = document.createElement('div');
        newDiv.id = 'appsDiv';
        newDiv.classList.toggle('widget');
        newDiv.innerHTML = appsHtml;
        newDiv.style.position = 'absolute';
        newDiv.style.top = image.top + window.scrollY + 'px';
        newDiv.style.left = image.left + window.scrollX-385 + 'px';
        document.body.appendChild(newDiv);

        if (!GM_getValue("auth").match("Full")){
            GM_addStyle (`div.plus-app{opacity:0.25;}`)
        };

        let serverNo;
        let server;
        if (window.location.toString().match('sigil')){
            serverNo = 1
            server = 'sigil'
        };
        if (window.location.toString().match('torax')){
            serverNo = 2
            server = 'torax'
        };
        const rgaName = document.querySelector("#rg_sess_id").value;
        const charId = document.body.innerHTML.match(/outwar\.com\/page\?x=([0-9]+)/i)[1];

        document.querySelector("#authApp").addEventListener('click',async function(){
            await appsMenuClose();
            await mmplus('AuthCheck|rganame');
        });
        document.querySelector("#exportRga").addEventListener('click',async function(){
            window.location.href = "ow_messagecenter?exportrga"
        });
        document.querySelector("#itemStorage").addEventListener('click',async function(){
            await blankOverlay(server,serverNo,rgaName,charId);
            await appItemStorage(server,serverNo,rgaName,charId);
        });
        document.querySelector("#illusionsApp").addEventListener('click',async function(){
            await blankOverlay(server,serverNo,rgaName,charId);
            await appIllusions(server,serverNo,rgaName,charId);
        });
        document.querySelector("#chaosTeles").addEventListener('click',async function(){
            await blankOverlay(server,serverNo,rgaName,charId);
            await appChaosTeles(server);
        });
        document.querySelector("#wildernessApp").addEventListener('click',async function(){
            await blankOverlay(server,serverNo,rgaName,charId);
            await appWilderness(server,serverNo,rgaName,charId);
        });
        document.querySelector("#savedRgas").addEventListener('click',async function(){
            await blankOverlay(server,serverNo,rgaName,charId);
            await appSavedRgas(server,serverNo,rgaName,charId);
        });
        document.querySelector("#itemAnalyzer").addEventListener('click',async function(){
            await blankOverlay(server,serverNo,rgaName,charId);
            await appItemAnalyzer(server,serverNo,rgaName,charId);
        });
        document.querySelector("#mobAttacker").addEventListener('click',async function(){
            await blankOverlay(server,serverNo,rgaName,charId);
            await appMobAttacker(server,serverNo,rgaName,charId);
        });
        document.querySelector("#mobRaider").addEventListener('click',async function(){
            await blankOverlay(server,serverNo,rgaName,charId);
            await appMobRaider(server,serverNo,rgaName,charId);
        });
        document.querySelector("#gladiatorApp").addEventListener('click',async function(){
            await blankOverlay(server,serverNo,rgaName,charId);
            await appGladiator(server,serverNo,rgaName,charId);
        });
        document.querySelector("#raidsReport").addEventListener('click',async function(){
            await blankOverlay(server,serverNo,rgaName,charId);
            await appRaidsReport(server,serverNo,rgaName,charId);
        });
        document.querySelector("#moxxiVision").addEventListener('click',async function(){
            window.location.href = "treasury.php?type=vision"
        });
        document.querySelector("#themeApp").addEventListener('click',async function(){
            await appCustomTheme();
        });
        document.querySelector("#reportBadge").addEventListener('click',async function(){
            await appsMenuClose();
            await mmplus(`BadgeNeeds|rganame|${server}`);
        });
        document.querySelector("#reportChaos").addEventListener('click',async function(){
            await appsMenuClose();
            await mmplus(`ChaosNeeds|rganame|${server}`);
        });
        document.querySelector("#reportRune").addEventListener('click',async function(){
            await appsMenuClose();
            await mmplus(`RuneNeeds|rganame|${server}`);
        });
        document.querySelector("#reportEnhancer").addEventListener('click',async function(){
            await appsMenuClose();
            await mmplus(`EnhanceNeeds|rganame|${server}`);
        });
        document.querySelector("#reportLing").addEventListener('click',async function(){
            await appsMenuClose();
            await mmplus(`LingNeeds|rganame|${server}`);
        });
        document.querySelector("#goToDiscord").addEventListener('click',async function(){
            window.open("https://discord.com/invite/f35cccbWU8?utm_source=Discord%20Widget&utm_medium=Connect", "_blank");
        });
    };

    GM_addStyle (`#appsDiv {animation: moveAnimation 0.5s ease forwards;position:fixed;}`)
    GM_addStyle (`@keyframes moveAnimation {0% {width:435px;height:0px;position:fixed;top:0px;} 100% {width:435px;height:535px;position:fixed;top:45px;}}`)
    appsMenuCreated = true;
};


async function exportrga(server,serverNo,rgaName,charId){
    await loadingOverlay();
    const chars = await superfetch(`ajax/accounts.php?t_serv=${serverNo}`);
    const profile = await superfetch(`profile`);
    const name = profile.match(/<font size="3">(.*?)<\/font>/i)[1].replace(/,/g,'');
    const ids = chars.match(/"id":"[0-9]+"/g).map(id => id.match(/[0-9]+/)[0]);
    let string = `ExportRGA|${server}|`
    for (let i = 0; i < ids.length; i++) {
        const id = ids[i];
        const profile = await superfetch(`profile?suid=${id}`);
        const equipment = await superfetch(`equipment?r=0&suid=${id}`);
        const array = [];
        const name = profile.match(/<font size="3">(.*?)<\/font>/i)[1].replace(/,/g,'');
        const level = profile.match(/<font size="2">Level ([0-9]+) .*?<\/font>/i)[1];
        const exp = profile.match(/TOTAL EXPERIENCE.*[\n\r].*<font size="2">(.*)<\/font>/i)[1].replace(/,/g,'');
        const mr = profile.match(/Maximum:<\/b><\/td><td>(.*?)<\/td><\/tr>/i)[1].replace(/,/g,'');
        const power = profile.match(/TOTAL POWER.*[\n\r].*<font size="2">(.*)<\/font><\/b><\/td>/i)[1].replace(/,/g,'');
        const ele = profile.match(/ELEMENTAL ATTACK.*[\n\r].*<font size="2">(.*)<\/font>/i)[1].replace(/,/g,'');
        const atk = profile.match(/ATTACK.*[\n\r].*<font size="2">(.*)<\/font>/i)[1].replace(/,/g,'');
        const hp = profile.match(/HIT POINTS.*[\n\r].*<font size="2">(.*)<\/font>/i)[1].replace(/,/g,'');
        const chaos = profile.match(/CHAOS DAMAGE.*[\n\r].*<font size="2">(.*)<\/font>/i)[1].replace(/,/g,'');
        const resist = profile.match(/ELEMENTAL RESIST.*[\n\r].*<font size="2">(.*)<\/font>/i)[1].replace(/,/g,'');
        const core = (equipment.match(/<.*?'slot10'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const head = (equipment.match(/<.*?'slot5'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const neck = (equipment.match(/<.*?'slot6'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const weapon = (equipment.match(/<.*?'slot3'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const body = (equipment.match(/<.*?'slot0'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const shield = (equipment.match(/<.*?'slot1'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const belt = (equipment.match(/<.*?'slot7'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const pants = (equipment.match(/<.*?'slot9'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const ring = (equipment.match(/<.*?'slot4'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const foot = (equipment.match(/<.*?'slot2'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const chaosgem = (equipment.match(/<.*?'slot17'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const badge = (equipment.match(/<.*?'slot12'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const rune = (equipment.match(/<.*?'slot11'.*?>/i) || [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const orbs = equipment.match(/<.*?'slot8'.*?>/g) || [];
        const orb1 = (orbs.length > 0 ? [orbs[0]] : [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const orb2 = (orbs.length > 1 ? [orbs[1]] : [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        const orb3 = (orbs.length > 2 ? [orbs[2]] : [`src="0" ONMOUSEOVER="itempopup(event,'0')"`]).map(i => i.match(/src="([^"]*)" ONMOUSEOVER="itempopup\(event,'([0-9]+)'\)"/i));
        array.push(name,level,exp,power,ele,resist,atk,hp,chaos,mr,core[0][1],core[0][2],head[0][1],head[0][2],neck[0][1],neck[0][2],weapon[0][1],weapon[0][2],body[0][1],body[0][2],shield[0][1],shield[0][2],belt[0][1],belt[0][2],pants[0][1],pants[0][2],ring[0][1],ring[0][2],foot[0][1],foot[0][2],chaosgem[0][1],chaosgem[0][2],rune[0][1],rune[0][2],orb1[0][1],orb1[0][2],orb2[0][1],orb2[0][2],orb3[0][1],orb3[0][2],badge[0][1],badge[0][2]);
        string += array.join(',').replace(/http:\/\/[A-Za-z]+\./g,'') + ',';
    };

    const url = await mmplus(string.slice(0,-1));
    const msg = await superfetch('send_ow_message');
    const nonce = msg.match(/name="form-nonce" value="([^"]*)"/i)[1];
    await superpost('send_ow_message',`totype=user&name=${name}&subject=Moxximod+v8+Export+RGA&message2=${url}&form-nonce=${nonce}&send=Send`)
    window.location = `ow_messagecenter?suid=${charId}`
};


async function appItemStorage(server,serverNo,rgaName,charId){

    document.querySelector("#overlayWidget").innerHTML = `
    <div id="itemFilterDiv" style="height:5%;"></div>
    <div id="itemStorageDiv" style="text-align:center;height:95%;overflow:auto;">
    <img src="https://studiomoxxi.com/moxximod/loading-gif.gif" style="height:100px;width:100px">
    </div>
    `

    const charDropdown = document.body.innerHTML.replace(/[\n\r]/g,'').match(/<optgroup label="My Characters">.*?<option value="0">--Change Server--<\/option>/i)
    const charIdArray = charDropdown.toString().match(/value="[0-9]+"/g).map(match => match.match(/[0-9]+/)[0]).slice(0, -1);

    let array = [];

    const inventory = async (id) => {
        const types = ['regular', 'quest', 'orb', 'potion', 'key'];

        const encounteredNames = new Set();
        for (const type of types) {
            const look = await superfetch(`ajax/backpackcontents.php?tab=${type}&suid=${id}`);
            const parse = look.match(/data-itemidqty="[0-9]+" data-name="[^"]*".*?src="[^"]*"/g);
            if (parse){
                const items = look.match(/data-itemidqty="[0-9]+" data-name="[^"]*".*?src="[^"]*"/g).map(i => [i.match(/data-name="([^"]*)"/i)[1], i.match(/data-itemidqty="([0-9]+)"/i)[1], i.match(/src="([^"]*)"/i)[1]]);
                for (let i = 0; i < items.length; i++) {
                    const [name] = items[i];

                    if (!encounteredNames.has(name)) {
                        array.push(items[i]);
                        encounteredNames.add(name);
                    };
                };
            };
        };
        const lookEq = await superfetch(`equipment?suid=${id}`);
        const equipped = (lookEq.match(/src="[^"]*" ONMOUSEOVER="itempopup\(event,'[0-9]+'\)" ONMOUSEOUT="kill\(\)" onclick="removeItem\('[0-9]+',[0-9]+,[0-9]+\);document\.getElementById\('[^']*'\)\.innerHTML=''" alt="[^"]*"/g) || []).map(item => [item.match(/alt="([^"]*)"/i)[1], "1", item.match(/src="([^"]*)"/i)[1]]);
        for (let i = 0; i < equipped.length; i++) {
            array.push(equipped[i]);
        };
    };
    await Promise.all(charIdArray.map(inventory));

    let combinedData = {};
    array.forEach(item => {
        let name = item[0];
        let quantity = parseInt(item[1]);
        if (combinedData[name]) {
            combinedData[name][1] += quantity;
        } else {
            combinedData[name] = [name, quantity, item[2]];
        };
    });
    let finalData = Object.values(combinedData);
    let tableData = []
    for (let i = 0; i < finalData.length; i++) {
        const item = finalData[i]
        tableData.push(`<tr><td><img src="${item[2]}" style="width:25px;height:25px"></td><td>${item[0]}</td><td>${item[1]}</td></tr>`)
    }
    document.querySelector("#itemFilterDiv").innerHTML = `<input type="text" class="form-control-new mb-3" "style="font-size:15px;width:50%;" id="filterInput" placeholder="Filter...">`
    document.querySelector("#itemStorageDiv").innerHTML = `
    <table id="inventory" class="table table-striped sortable">
    <thead><tr><th>Image</th><th>Item</th><th>Qnt</th></tr></thead>
    <tbody>${tableData.join('')}</tbody>
    </table>
    `

    document.getElementById("filterInput").addEventListener("keyup", function() {
        var filter = this.value.toLowerCase();
        var rows = document.querySelectorAll("#inventory tr");

        rows.forEach(function(row, index) {
            if (index === 0) return;
            var cells = row.getElementsByTagName("td");
            var showRow = false;
            for (var i = 0; i < cells.length; i++) {
                var cell = cells[i];
                if (cell.textContent.toLowerCase().indexOf(filter) > -1) {
                    showRow = true;
                    break;
                }
            }
            row.style.display = showRow ? "" : "none";
        });
    });

    sortableTables();
};


async function appIllusions(server,serverNo,rgaName,charId){

    GM_addStyle (`
    .form-control-new{height:30px;width:350px;margin:3px;padding-left:10px;}
    #search > img{height:40px;width:40px;margin:5px;border-radius:5px;border:2px #475254 SOLID;background-color:#000000;}
    `)

    document.querySelector("#overlayWidget").innerHTML = `
    <center>
    <!-- Search boxes -->
    <div class="row justify-content-center">
    <div class="col-xl-3 col-lg-6 col-md-6 col-sm-12 col-12 layout-spacing px-1">
    <h3>Illusion Item Search</h3>
    <form class="form" id="myForm" action="https://torax.outwar.com/livesearchcore/AjaxProcessor.php" method="post">
    <input type="text" name="slot10" class="illusion-search form-control-new" autocomplete="off" placeholder="Core">
    </form>
    <form class="form" id="myForm" action="https://torax.outwar.com/livesearchcore/AjaxProcessor.php" method="post">
    <input type="text" name="slot5" class="illusion-search form-control-new" autocomplete="off" placeholder="Head">
    </form>
    <form class="form" id="myForm" action="https://torax.outwar.com/livesearchcore/AjaxProcessor.php" method="post">
    <input type="text" name="slot6" class="illusion-search form-control-new" autocomplete="off" placeholder="Neck">
    </form>
    <form class="form" id="myForm" action="https://torax.outwar.com/livesearchcore/AjaxProcessor.php" method="post">
    <input type="text" name="slot3" class="illusion-search form-control-new" autocomplete="off" placeholder="Weapon">
    </form>
    <form class="form" id="myForm" action="https://torax.outwar.com/livesearchcore/AjaxProcessor.php" method="post">
    <input type="text" name="slot0" class="illusion-search form-control-new" autocomplete="off" placeholder="Body">
    </form>
    <form class="form" id="myForm" action="https://torax.outwar.com/livesearchcore/AjaxProcessor.php" method="post">
    <input type="text" name="slot1" class="illusion-search form-control-new" autocomplete="off" placeholder="Shield">
    </form>
    <form class="form" id="myForm" action="https://torax.outwar.com/livesearchcore/AjaxProcessor.php" method="post">
    <input type="text" name="slot7" class="illusion-search form-control-new" autocomplete="off" placeholder="Belt">
    </form>
    <form class="form" id="myForm" action="https://torax.outwar.com/livesearchcore/AjaxProcessor.php" method="post">
    <input type="text" name="slot9" class="illusion-search form-control-new" autocomplete="off" placeholder="Pants">
    </form>
    <form class="form" id="myForm" action="https://torax.outwar.com/livesearchcore/AjaxProcessor.php" method="post">
    <input type="text" name="slot4" class="illusion-search form-control-new" autocomplete="off" placeholder="Ring">
    </form>
    <form class="form" id="myForm" action="https://torax.outwar.com/livesearchcore/AjaxProcessor.php" method="post">
    <input type="text" name="slot2" class="illusion-search form-control-new" autocomplete="off" placeholder="Foot">
    </form>
    </div>
    <!-- The dude -->
    <div class="col-xl-3 col-lg-6 col-md-6 col-sm-12 col-12 layout-spacing px-1"">
    <div style="position:relative; width:300px; height:385px; background-image:url(/images/thedude.png)" id="thedude">
    <div id="slot10" class="illusion-slot" style="position:absolute; left:61px; top:12px; width:41px; height:41px;text-align:center"></div>
    <div id="slot5" class="illusion-slot" style="position:absolute; left:118px; top:7px; width:62px; height:46px;text-align:center"></div>
    <div id="slot6" class="illusion-slot" style="position:absolute; left:197px; top:12px; width:41px; height:41px;text-align:center"></div>
    <div id="slot3" class="illusion-slot" style="position:absolute; left:45px; top:67px; width:56px; height:96px;text-align:center"></div>
    <div id="slot0" class="illusion-slot" style="position:absolute; left:121px; top:67px; width:56px; height:96px;text-align:center"></div>
    <div id="slot1" class="illusion-slot" style="position:absolute; left:198px; top:67px; width:56px; height:96px;text-align:center"></div>
    <div id="slot9" class="illusion-slot" style="position:absolute; left:118px; top:175px; width:62px; height:75px;text-align:center"></div>
    <div id="slot7" class="illusion-slot" style="position:absolute; left:61px; top:192px; width:41px; height:41px;text-align:center"></div>
    <div id="slot4" class="illusion-slot" style="position:absolute; left:197px; top:192px; width:41px; height:41px;text-align:center"></div>
    <div id="slot2" class="illusion-slot" style="position:absolute; left:118px; top:262px; width:62px; height:66px;text-align:center"></div>
    </div>
    Click item to remove<br>
    </div>
    <!-- List of items -->
    <div class="col-xl-3 col-lg-6 col-md-6 col-sm-12 col-12 layout-spacing px-1" style="text-align:left;">
    <div class="list-group text-left">
    <div class="list-group-item">CORE: <span id="txtslot10"></span></div>
    <div class="list-group-item">HEAD: <span id="txtslot5"></span></div>
    <div class="list-group-item">NECK: <span id="txtslot6"></span></div>
    <div class="list-group-item">WEAPON: <span id="txtslot3"></span></div>
    <div class="list-group-item">BODY: <span id="txtslot0"></span></div>
    <div class="list-group-item">SHIELD: <span id="txtslot1"></span></div>
    <div class="list-group-item">BELT: <span id="txtslot7"></span></div>
    <div class="list-group-item">PANTS: <span id="txtslot9"></span></div>
    <div class="list-group-item">RING: <span id="txtslot4"></span></div>
    <div class="list-group-item">FOOT: <span id="txtslot2"></span></div>
    </div>
    </div>
    </div>
    <!-- Item search results -->
    <div id="search"></div>
    `

    const eq = await superfetch('equipment?r=0');
    const items = eq.match(/src="[^"]*" ONMOUSEOVER="itempopup\(event,'[0-9]+'\)" ONMOUSEOUT="kill\(\)" onclick="removeItem\('[0-9]+',[0-9]+,[0-9]+\);document\.getElementById\('slot[0-9]+'\)/g);
    const slots = items.map(i => i.match(/slot[0-9]+/)[0]);
    for (let i = 0; i < slots.length; i++) {
        const slot = slots[i]
        const dude = document.querySelector(`#${slot}`)
        if (dude){
            const regex = new RegExp(`src="[^"]*" ONMOUSEOVER="itempopup\\(event,'[0-9]+'\\)" ONMOUSEOUT="kill\\(\\)" onclick="removeItem\\('[0-9]+',[0-9]+,[0-9]+\\);document\.getElementById\\('${slot}'\\)`);
            const img = eq.match(regex).toString().match(/src="([^"]*)"/i)[1];
            const iid = eq.match(regex).toString().match(/event,'([0-9]+)'/i)[1];
            dude.setAttribute('alt',iid)
            dude.innerHTML = `<img src="${img}">`
        };
    };

    const dudeSlot = document.querySelectorAll(".illusion-slot");
    for (let i = 0; i < dudeSlot.length; i++) {
        dudeSlot[i].addEventListener('click', function(){
            const slot = dudeSlot[i].outerHTML.match(/id="([^"]*)"/i)[1];
            document.querySelector(`#txt${slot}`).innerHTML = '';
            dudeSlot[i].innerHTML = ''
        });
    };

    const search = document.querySelectorAll(".illusion-search");
    for (let i = 0; i < search.length; i++) {
        search[i].addEventListener('input', async function(){
            const value = search[i].value;
            const html = search[i].outerHTML
            const slot = html.match(/name="([^"]*)"/i)[1]
            const dude = document.querySelector(`#${slot}`).outerHTML
            const iid = dude.match(/alt="([^"]*)"/i)[1]
            const post = await fetch('livesearchcore/AjaxProcessor.php', {
                method: 'POST',
                headers: { "content-type": "application/x-www-form-urlencoded; charset=UTF-8","x-requested-with": "XMLHttpRequest" },
                body: `ls_anti_bot=ajaxlivesearch_guard&ls_token=${iid}&ls_page_loaded_at=0&ls_current_page=1&ls_query_id=ls_query&ls_query=${value}&ls_items_per_page=10000`
            });
            const data = await post.text();

            const resultPrint = data.replace(/\\/g,'').match(/<td style=''>.*?<\/td><td style=''><img src=".*?">/g).slice(1).toString().replace(/<\/td><td style=''><img /g,'" ').replace(/<td style=''>/g,'<img name="').replace(/,/g,'').replace(/src/g,`class="${slot}" src`);
            document.querySelector("#search").innerHTML = resultPrint;

            const resultSelect = document.querySelectorAll(`.${slot}`)
            for (let i = 0; i < resultSelect.length; i++) {
                const node = resultSelect[i];
                node.addEventListener('click', function() {
                    const img = node.outerHTML.match(/src="([^"]*)"/i)[1]
                    const name = node.outerHTML.match(/name="([^"]*)"/i)[1]
                    document.querySelector(`#${slot}`).innerHTML = `<img src="${img}">`
                    document.querySelector(`#txt${slot}`).innerHTML = name;
                });
            };
        });
    };
};


async function appCustomTheme(){

    await appsMenuClose();

    GM_addStyle(`
    .widget {-webkit-box-shadow: 0px 0px 3px 3px rgba(0,0,0,1);}
    .widget-content-area {-webkit-box-shadow: 0px 0px 3px 3px rgba(0,0,0,1);}
    #premadeThemes {white-space: nowrap;padding:15px;border-radius:10px;}
    .premadeDiv {display:inline-block;text-align:center;font-size:9px;font-family:monospace;}
    img.premade{transition: .5s ease-out;height:100px;width:100px;border-radius:10px;box-shadow:0 5px 5px 0 rgba(0,0,0,1);border:2px #475254 SOLID;margin:10px;cursor:pointer;}
    img.premade:hover{filter: saturate(250%);}
    `)

    document.querySelector("#content").innerHTML = `
    <!-- Header Widget -->
    <div class="widget" style="width:1115px !important;margin-top:0.5rem;">
    <h3>Outwar Theme</h3>
    Enter all colors as 6-digit <a href="https://htmlcolorcodes.com/" target="_blank">hexadecimal</a> codes
    <hr>
    <button class="btn-mm" id="updateTheme">UPDATE THEME</button><button class="btn-mm" id="resetTheme">RESET THEME</button>
    </div>
    <!-- Premade Themes -->
    <div class="widget" style="width:1115px !important;margin-top:1rem;">
    <div class="list-group-item" style="width:100%;overflow:auto;text-align:left;max-width:100% !important;" id="premadeThemes">
    </div>
    </div>
    <!-- Lower Widget -->
    <div class="row justify-content-center">
    <!-- Left -->
    <div style="margin:1rem;width:350px">
    <!-- Background Image -->
    <div class="widget widget-chart-one mb-3" style="text-align:left">
    background image url
    <input style="width:100%;" id="themeBgImg" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    </div>
    <!-- Text and links -->
    <div class="widget widget-chart-one mb-3" style="text-align:left">
    text color
    <input style="width:100%;" id="themeTxt" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    link color
    <input style="width:100%;" id="themeLink" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    link hover color
    <input style="width:100%;" id="themeLinkHover" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    </div>
    <!-- Scrollbar -->
    <div class="widget widget-chart-one mb-3" style="text-align:left">
    scrollbar slider color
    <input style="width:100%;" id="themeScrollSlider" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    scrollbar track color
    <input style="width:100%;" id="themeScrollTrack" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    </div>
    </div>
    <!-- Middle -->
    <div style="margin:1rem;width:350px">
    <!-- Toolbar and Widget Color -->
    <div class="widget widget-chart-one mb-3" style="text-align:left">
    toolbar background color
    <input style="width:100%;" id="themeToolbarBg" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    main content background color
    <input style="width:100%;" id="themeContentBg" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    </div>
    <!-- Tables -->
    <div class="widget widget-chart-one mb-3" style="text-align:left">
    table background color
    <input style="width:100%;" id="themeTableBg" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    table header text color
    <input style="width:100%;" id="themeTableHeaderTxt" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    table text color
    <input style="width:100%;" id="themeTableTxt" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    </div>
    </div>
    <!-- Right -->
    <div style="margin:1rem;width:350px">
    <!-- Text Boxes and Buttons -->
    <div class="widget widget-chart-one mb-3" style="text-align:left">
    button and textbox background color
    <input style="width:100%;" id="themeBoxBg" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    button and textbox text color
    <input style="width:100%;" id="themeBoxTxt" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    </div>
    <!-- Menu -->
    <div class="widget widget-chart-one mb-3" style="text-align:left">
    menu background color
    <input style="width:100%;" id="themeMenuBg" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    menu text color
    <input style="width:100%;" id="themeMenuTxt" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    menu hover color
    <input style="width:100%;" id="themeMenuHover" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    menu subtext color
    <input style="width:100%;" id="themeMenuSubTxt" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    menu subtext hover
    <input style="width:100%;" id="themeMenuSubTxtHover" type="text" class="form-control-new mb-2 theme-input" autocomplete="off">
    </div>
    </div>
    </div>
    `

    const premadeDetails = {
        1: ['vordyn','F6DCF5','EE6CD7','F8C2F2','EE6CD7','F8C2F2','842266','300E25','292438','EE6CD7','F8C2F2','191320','F6DCF5','191320','F6DCF5','842266','EE6CD7','F8C2F2'],
        2: ['alvar','CDE5FA','45B0DB','274E83','274E83','0D2F4C','0D2F4C','0B1426','08335E','274E83','CDE5FA','274E83','CDE5FA','274E83','CDE5FA','45B0DB','CDE5FA','45B0DB'],
        3: ['delruk','FDE9D6','FDBB5F','FE7626','FE7626','6A241C','6A241C','290C08','18080A','FE7626','FDE9D6','B84313','FDE9D6','18080A','FDBB5F','FE7626','B84313','FE7626'],
        4: ['lagoon','B8C6C3','EDEEDB','23466A','23466A','161C2A','142335','0F151C','66706A','9BB1B5','B8C6C3','132A45','ABBDBE','141D2A','ABBDBE','727C76','9BB1B5','B8C6C3'],
        5: ['triangle','FCFFFF','DA8D95','77573A','77573A','0F0613','0F0613','171C28','1D1221','DA8D95','FCFFFF','77573A','FCFFFF','142936','FCFFFF','77573A','DA8D95','77573A'],
        6: ['cyberpunk','C1C5CD','FD3FF5','6EC4EF','6EC4EF','1A1A16','1C1C3C','1A1A16','281842','6EC4EF','C1C5CD','1C1C3C','C1C5CD','04202D','FD3FF5','6EC4EF','C1C5CD','6EC4EF'],
        7: ['haze','FDFDFD','AE9ADE','EFB9EB','EFB9EB','181F3A','303148','181F3A','39374E','EFB9EB','FDFDFD','3A3E51','EFB9EB','3A3E51','FDFDFD','AE9ADE','AE9ADE','FDFDFD'],
        8: ['leather','ffffff','907552','ffffff','907552','272017','272017','070508','272017','907552','ffffff','272017','ffffff','11120F','ffffff','272017','ffffff','907552'],
        9: ['doodle','1F94BA','15C391','85446C','1F94BA','1D1C21','1D1C21','1D1C21','1D1C21','576590','873F63','1E9EC2','1D1C21','1D1C21','645A7D','18A9AA','18A9AA','15C391'],
        10: ['ring','ffffff','E7A300','ffffff','E7A300','1D1D1D','070707','0C0C0C','1D1D1D','E7A300','ffffff','1D1D1D','ffffff','1D1D1D','E7A300','0C0C0C','ffffff','E7A300'],
        11: ['woods','d5d5d5','828282','d5d5d5','3D3D3D','111111','1A1A1A','111111','242424','828282','d5d5d5','0D0D0D','d5d5d5','1A1A1A','d5d5d5','5B5B5B','5B5B5B','d5d5d5'],
        12: ['view','CEE4EA','5AC5D1','5A8081','5AC5D1','12353D','12353D','030911','0E312C','5A8081','CEE4EA','153833','0E312C','CEE4EA','B3D6E3','5A8081','5AC5D1'],
        13: ['carbon','BFBDBC','C61C30','43413F','E22F35','050303','050303','1F1C1D','1F1C1D','C61C30','BFBDBC','1F1C1D','E22F35','0E0C0D','BFBDBC','43413F','BFBDBC','C61C30'],
        14: ['classic','d3d3d3','d3d3d3','fff000','3D3D3D','1B1B1B','1B1B1B','0b0b0b','232323','fff000','d3d3d3','282828','d3d3d3','0b0b0b','d3d3d3','232323','fff000','d3d3d3'],
        15: ['sunrise','FAC7DC','50B3B1','DB5B7F','50B3B1','122034','0F1E32','09181F','122034','DB5B7F','FAC7DC','221424','C95175','3F2E42','50B3B1','FF90A1','47AAAF','FAC7DC'],
        16: ['spotlight','b2b2b2','939393','FFFFFF','b2b2b2','181818','060606','181818','262626','b2b2b2','939393','262626','b2b2b2','181818','b2b2b2','262626','b2b2b2','939393'],
        17: ['calibrate','ffffff','CEF382','EE9B5A','EE9B5A','024671','5c3047','234259','024671','CEF382','d1a8a2','3c274c','EE7462','003150','CEF382','4D69A1','EE9B5A','d1a8a2'],
        18: ['lake','7AB0EE','908D5C','5896E0','76ADE1','0F2336','2E3447','0B0E16','2E3543','76ADE1','ffffff','2E3543','ffffff','0B0E16','ffffff','7AB0EE','D3A145','76ADE1'],
        19: ['osiris','67C5F8','F7F554','ffffff','67C5F8','111219','13161E','191925','333340','ffffff','ffffff','090A11','ffffff','090A11','ffffff','0754A1','67C5F8','F7F554'],
        20: ['cove','ffffff','14E7D9','EE9B5A','EE9B5A','171954','5c3047','120C42','024671','CEF382','d1a8a2','3c274c','EE7462','210D51','EA9DAC','4D69A1','EE9B5A','d1a8a2'],
        21: ['river','D9E4F6','C3E5F2','E57EAC','D9E4F6','121E2A','080C12','080C12','061A41','D9E4F6','E57EAC','121E2A','E57EAC','121E2A','E57EAC','061A41','D9E4F6','C3E5F2']
    };

    const premadeCount = Object.keys(premadeDetails).length;
    const premadeArray = [];
    for (let i = 1; i <= premadeCount; i++) {
        premadeArray.push(`
            <div class="premadeDiv">
            <img src="https://studiomoxxi.com/moxximod/plus_wallpapers/${i}.webp" class="premade" id="premade${i}"><br>
            ${premadeDetails[i][0].toUpperCase()}
            </div>
        `);
    };

    document.querySelector("#premadeThemes").innerHTML = premadeArray.join('');
    for (let i = 1; i <= premadeCount; i++) {
        document.querySelector(`#premade${i}`).addEventListener('click', async function(){

            document.querySelector("#themeBgImg").value = `https://studiomoxxi.com/moxximod/plus_wallpapers/${i}.webp`

            const inputs = document.querySelectorAll('input.theme-input');

            for (let x = 1; x < inputs.length; x++) {
                if (premadeDetails[i][x]){
                    inputs[x].value = premadeDetails[i][x];
                };
            };
        });
    };

    document.querySelector("#updateTheme").addEventListener('click', async function(){

        const inputs = document.querySelectorAll('input.theme-input');

        const hexArray = [];
        inputs.forEach(async element => {

            const value = element.value.replace(/#/g,'');
            const id = element.id

            if ((/^\w{6}$/.test(value) || id == "themeBgImg") || value == '') {
                if (value != ''){
                    GM_setValue(id,value);
                    if (!value.match('studiomoxxi')){
                        hexArray.push(`'${value}'`);
                    };
                };
            } else {
                alert(`Invalid entry for ${id}. Please make sure all values are 6-digit hex codes`);
                return;
            };
        });

        console.log(`Theme value array: ${hexArray.join(',')}`)
        await loadCustomTheme();
    });

    document.querySelector("#resetTheme").addEventListener('click', async function(){
        const inputs = document.querySelectorAll('input.theme-input');
        inputs.forEach(async element => {
            const id = element.id
            GM_deleteValue(id);
        });
        window.location = window.location;
    });
};


async function loadCustomTheme(){
    if (GM_getValue("themeBoxBg")){
        const value = GM_getValue("themeBoxBg");
        GM_addStyle(`
            .form-control-new {background:#${value} !important}
            .form-control {background:#${value} !important}
            .btn-mm {background-color:#${value} !important;}
            .btn-primary {background-color:#${value} !important;border:0px SOLID !important;}
            .btn {background-color:#${value} !important;border:0px SOLID !important;}
            .swal2-popup {background-color:#${value} !important}
            .btn-info{background-color:#${value} !important;}
            .alert-light-warning{background-color:#${value} !important;}
        `);
    };
    if (GM_getValue("themeBoxTxt")){
        const value = GM_getValue("themeBoxTxt");
        GM_addStyle(`
            .form-control-new {color:#${value} !important}
            .form-control-new::placeholder {color:#${value} !important;opacity:0.3;}
            .form-control {color:#${value} !important}
            .form-control::placeholder {color:#${value} !important;opacity:0.3;}
            .btn-mm {color:#${value} !important;}
            .btn-primary {color:#${value} !important;border:0px SOLID !important;}
            .btn {color:#${value} !important;border:0px SOLID !important;}
            .swal2-popup {color:#${value} !important}
            .btn-info {color:#${value} !important}
            .alert-light-warning{color:#${value} !important}
            #mailCollapseTwo > div > div.alert.alert-light-warning.border-0.mb-4 > button > svg{color:#${value} !important}
            body{color:#${value} !important;}
        `);
    };
    if (GM_getValue("themeBgImg")){
        const value = GM_getValue("themeBgImg");
        var height = window.screen.availHeight
        var width = window.screen.availWidth
        GM_addStyle(`
            body > center{background-image: url("${value}") !important;
            background-size: ${width}px ${height}px !important;
            background-attachment: fixed !important;
            background-position:center !important;
            background-repeat:no-repeat !important;
        `);
    };
    if (GM_getValue("themeScrollSlider") && GM_getValue("themeScrollTrack")){
        const value1 = GM_getValue("themeScrollSlider");
        const value2 = GM_getValue("themeScrollTrack");
        GM_addStyle(`
            * {scrollbar-color: #`+value1+` #`+value2+`;}
            *::-webkit-scrollbar-track {background:#`+value2+`;}
            *::-webkit-scrollbar-thumb {background-color:#`+value1+`;}
            * {scrollbar-width: 7px;}
            *::-webkit-scrollbar {width: 7px;}
        `);
    };
    if (GM_getValue("themeToolbarBg")){
        const value = GM_getValue("themeToolbarBg");
        GM_addStyle(`
            .navbar {background:#${value} !important;}
            #sidebar ul.menu-categories li.menu > .dropdown-toggle[aria-expanded=true] {background:#${value} !important;}
            .nav-link.active {background-color: #${value} !important; border-color: #${value} !important;}
            .nav-tabs {border-bottom: #${value} !important;}
        `);
    };
    if (GM_getValue("themeContentBg")){
        const value = GM_getValue("themeContentBg");
        GM_addStyle(`
            .widget {background-color:#${value}}
            .widget-content-area {background-color:#${value}}
            .widget-content {background-color:#${value}}
            .custom-dropdown-menu {background-color:#${value} !important;}
            .swal2-modal {background-color: #${value} !important;}
            #bpWin_handle {background-color: #${value} !important;}
            #eqWin_handle {background-color: #${value} !important;}
            .widget-header{background-color:#${value} !important;}
            .modal-content{background-color:#${value} !important;}
            .mailbox-inbox{background-color:#${value} !important;}
            .content-box{background-color:#${value} !important;}
            .msg-close{background:#${value} !important;}
        `);
    };
    if (GM_getValue("themeTableBg")){
        const value = GM_getValue("themeTableBg");
        GM_addStyle(`
            .table {background-color:#${value} !important;}
            .table-striped {background-color:#${value} !important;}
            .list-group-item {background-color: #${value} !important;}
            .wquesttable{background-color: #${value} !important;}
            .list-group-item {border: #${value} 1px SOLID !important;margin-bottom:4px !important;}
            .b-skills {background-color: #${value} !important;}
            hr {border-top: 1px SOLID #${value} !important;}
            .skillsbox{background-color:#${value} !important;}
            .modal-footer{border-top: 1px SOLID #${value} !important;}
            .modal-header{border: 1px SOLID #${value} !important;}
            .page-link{background:#${value} !important;}
            .page-link{background:#${value} !important;}
            #zero-config_info {border: 1px SOLID #${value} !important;}
            #mailHeadingEleven > div > div{background:#${value} !important;}
            #content-header-row > div > div > div > div > div.tab-title{background:#${value} !important;}
            p.mail-content.text-left{border-top: 1px SOLID #${value} !important;}
            div.d-flex.msg-close{border-bottom: 1px SOLID #${value} !important;}
            td[id*="questStep"]{background-color:#${value} !important;}
        `);
    };
    if (GM_getValue("themeTableHeaderTxt")){
        const value = GM_getValue("themeTableHeaderTxt");
        GM_addStyle(`
            .table > thead > tr > th {color:#${value} !important;}
            .table {border:#${value} SOLID 1px !important;}
            .table > tbody > tr {border:#${value} SOLID 1px !important;}
            .table > thead {border-top:#${value} SOLID 1px !important;}
            .table > border-collapse: revert !important;}
            .table-striped > thead > tr > th {color:#${value} !important;}
            .table-striped {border:#${value} SOLID 1px !important;}
            .table-striped > tbody > tr {border:#${value} SOLID 1px !important;}
            .table-striped > thead {border-top:#${value} SOLID 1px !important;}
            .table-striped > border-collapse: revert !important;}
            table.dataTable > thead > tr > th {color:#${value} !important;}
            table.dataTable {border:#${value} SOLID 1px !important;}
            table.dataTable > tbody > tr {border:#${value} SOLID 1px !important;}
            table.dataTable > thead {border-top:#${value} SOLID 1px !important;}
            table.dataTable {border-collapse: revert !important;}
        `);
    };
    if (GM_getValue("themeTableTxt")){
        const value = GM_getValue("themeTableTxt");
        GM_addStyle(`
            .table > tbody > tr > td {color:#${value} !important;}
            .table-striped > tbody > tr > td {color:#${value} !important;}
            #eqWin_handle > tbody > tr > td {color:#${value} !important;}
            #bpWin_handle > tbody > tr > td {color:#${value} !important;}
        `);
    };
    if (GM_getValue("themeTxt")){
        const value = GM_getValue("themeTxt");
        GM_addStyle(`
        .list-group.list-group-media{color:#${value} !important;}
        .list-group.list-group-media{color:#${value} !important;}
        .list-group-item{color:#${value} !important;}
        .media{color:#${value} !important;}
        .media-body{color:#${value} !important;}
        h6{color:#${value} !important;}
        h5{color:#${value} !important;}
        h4{color:#${value} !important;}
        h3{color:#${value} !important;}
        .list-group-item{color:#${value} !important;}
        .media{color:#${value} !important;}
        .media-body{color:#${value} !important;}
        p{color:#${value} !important;}
        .list-group-item{color:#${value} !important;}
        .bio{color:#${value} !important;}
        .widget{color:#${value} !important;}
        .widget-content-area{color:#${value} !important;}
        #cvMsg{color: #${value} !important;}
        div.dataTables_wrapper{color: #${value} !important;}
        div.dataTables_length label{color: #${value} !important;}
        `);
    };
    if (GM_getValue("themeLink")){
        const value = GM_getValue("themeLink");
        GM_addStyle(`
            a:not(.dropdown-toggle):not(.form-control-new){color:#${value} !important;}
            .form-control-new{border: 1px SOLID #${value} !important;}
            .form-control{border: 1px SOLID #${value} !important;}
            div.dataTables_wrapper{color:#${value} !important;}
            div.dataTables_info{color:#${value} !important;}
            #mailInbox > svg{color:#${value} !important;}
            #draft > svg{color:#${value} !important;}
            #sentmail > svg{color:#${value} !important;}
            #trashed > svg{color:#${value} !important;}
            #btn-compose-mail{display:none !important;}
            td[id*="questStep"] > a > font > b{color:#${value} !important;}
        `);
    };
    if (GM_getValue("themeLinkHover")){
        const value = GM_getValue("themeLinkHover");
        GM_addStyle(`
            a:not(.dropdown-toggle):not(.form-control-new):hover{color:#${value} !important;}
        `);
    };
    if (GM_getValue("themeMenuBg")){
        const value = GM_getValue("themeMenuBg");
        GM_addStyle(`
            #accordionExample{background:#${value} !important;}
            #sidebar{background:#${value} !important;}
            .dropdown-menu {background: #${value} !important;border:0px SOLID !important;}
            .nav-link.active{background-color:#${value} !important;}
            .nav-link.active{border-color:#${value} !important;}
        `);
    };
    if (GM_getValue("themeMenuTxt")){
        const value = GM_getValue("themeMenuTxt");
        GM_addStyle(`
            a.dropdown-toggle {color:#${value} !important;}
            #sidebar ul.menu-categories li.menu>.dropdown-toggle svg {color:#${value} !important;}
        `);
    };
    if (GM_getValue("themeMenuHover")){
        const value = GM_getValue("themeMenuHover");
        GM_addStyle(`
            #sidebar ul.menu-categories li.menu > .dropdown-toggle.dropdown-toggle:hover {background:#${value} !important;}
            .btn-group .dropdown-menu a.dropdown-item:hover {background:#${value} !important;}
            .btn-group .dropdown-menu .dropdown-item:hover {background:#${value} !important;}
        `);
    };
    if (GM_getValue("themeMenuSubTxt")){
        const value = GM_getValue("themeMenuSubTxt");
        GM_addStyle(`
            #sidebar ul.menu-categories ul.submenu > li a {color:#${value} !important;}
        `);
    };
    if (GM_getValue("themeMenuSubTxtHover")){
        const value = GM_getValue("themeMenuSubTxtHover");
        GM_addStyle(`
        #sidebar ul.menu-categories ul.submenu>li a:hover:before {background-color:#${value} !important;}
        #sidebar ul.menu-categories ul.submenu > li a:hover {color:#${value} !important;}
        `);
    };
};


async function appChaosTeles(server){
    document.querySelector("#overlayWidget").innerHTML = `
    <center>
    <img src="https://studiomoxxi.com/moxximod/loading-gif.gif" style="height:100px;width:100px">`
    const charDropdown = document.body.innerHTML.replace(/[\n\r]/g,'').match(/<optgroup label="My Characters">.*?<option value="0">--Change Server--<\/option>/i)
    const charIdArray = charDropdown.toString().match(/value="[0-9]+"/g).map(match => match.match(/[0-9]+/)[0]).slice(0, -1);
    let tableRows = []
    let totalTeles = 0
    const inventory = async (id) => {
        const kBp = await superfetch(`ajax/backpackcontents.php?tab=key&suid=${id}`);
        if (kBp.match(/data-itemidqty="[0-9]+" data-name="Arena Teleporter"/i)){
            const teleporters = parseInt(kBp.match(/data-itemidqty="([0-9]+)" data-name="Arena Teleporter"/i)[1]);
            const profile = await superfetch(`profile?suid=${id}`);
            const name = profile.match(/<font size="3">(.*?)<\/font>/i)[1];
            const rage = (parseInt(profile.replace(/[\n\r,]/g, '').match(/<span class="toolbar_rage">(.*?)<span>/i)[1])).toLocaleString();
            const circ = profile.match(/Circumspect/i) ? "Yes" : "No";
            const power = parseInt(profile.replace(/,/g,'').match(/TOTAL POWER<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]).toLocaleString();
            const ele = parseInt(profile.replace(/,/g,'').match(/ELEMENTAL ATTACK<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]).toLocaleString();
            tableRows.push(`<tr><td>${name}</td><td>${power}</td><td>${ele}</td><td>${rage}</td><td>${circ}</td><td>${teleporters}</td></tr>`);
            totalTeles += teleporters;
        };
    };
    await Promise.all(charIdArray.map(inventory));
    document.querySelector("#overlayWidget").innerHTML = `
    <table class="table table-striped mb-3" id="arenaTeleTable">
    <thead><tr><th>Character</th><th>Power</th><th>Elemental</th><th>Rage</th><th>Circumspect Cast</th><th>Arena Teleporters</th></thead>
    <tbody>
    ${tableRows.join('')}
    </tbody>
    </table>
    <brr><center>
    <button class="btn-mm" id="useTeleporters"></button>
    `
    if (totalTeles > 0){
        document.querySelector("#useTeleporters").innerHTML = `USE ${totalTeles} ARENA TELEPORTERS`
        document.querySelector("#useTeleporters").addEventListener('click', async function() {
            document.querySelector("#useTeleporters").remove();
            await mmplus(`ChaosTele|rganame|${server}`);
        });
    } else {
        document.querySelector("#arenaTeleTable").remove();
        document.querySelector("#useTeleporters").outerHTML = `YOU HAVE NO ARENA TELEPORTERS TO USE`
    };
};


async function appWilderness(server,serverNo,rgaName,charId){

    GM_addStyle(`
        div.wilderness-div{width:100%;text-align:center;}
        img.wilderness-mob-img{border-radius:10px;box-shadow:0 5px 5px 0 rgba(0,0,0,1);margin-bottom:1rem;height:250px;width:250px;}
        input.txt {background: #FFFFFF !important;color: #000000 !important;opacity: 1 !important;}
        .wilderness-info{margin-bottom:1rem;width:250px;}
        .wilderness-info-div{display:inline-block;margin-right:4px;margin-left:4px;}
    `)

    document.querySelector("#overlayWidget").innerHTML = `
    <div class="wilderness-div">
    <div id="wildernessLvl"></div>
    <div id="wildernessImg"><img src="https://studiomoxxi.com/moxximod/loading-gif.gif" style="height:100px;width:100px;margin-bottom:1rem;"></div>
    <div id="wildernessInfo">
    <div class="wilderness-info-div">
    <div class="form-control-new wilderness-info" style="padding:1rem;opacity:1 !important;">
    WINS<br>
    <input id="wildernessWins" type="number" class="form-control-new txt" style="width:180px;" disabled>
    </div><br>
    <div class="form-control-new wilderness-info" style="padding:1rem;opacity:1 !important;">
    LOSSES<br>
    <input id="wildernessLosses" type="number" class="form-control-new txt" style="width:180px;" disabled>
    </div>
    </div>
    <div class="wilderness-info-div">
    <div class="form-control-new wilderness-info" style="padding:1rem;opacity:1 !important;">
    TOTAL<br>
    <input id="wildernessTotal" type="number" class="form-control-new txt" style="width:180px;" disabled>
    </div><br>
    <div class="form-control-new wilderness-info" style="padding:1rem;opacity:1 !important;">
    BEST <img src="images/questwiki.jpg" onmouseover="statspopup(event,'% health remaining of best attack against current mob')" onmouseout="kill()" style="margin-bottom:5px;"><br>
    <input id="wildernessBest" type="number" class="form-control-new txt" style="width:180px;" disabled>
    </div>
    </div>
    </div>
    <button class="btn-mm" id="startWilderness">START</button>
    </div>
    `
    const atkLink = await appWildernessLoad()
    document.querySelector("#startWilderness").addEventListener('click', async function(){
        await appWildernessAttack(atkLink,0,0,100000000);
    });
};

async function appWildernessLoad(){
    const wilderness = await superfetch('wilderness',true);
    const atkLink = wilderness.match(/id="wildernessLink" href="([^"]*)"/i)[1];
    document.querySelector("#wildernessLvl").innerHTML = `<h1> LEVEL ${wilderness.match(/<h1>(.*?)<\/h1>/i)[1]}</h1>`;
    document.querySelector("#wildernessImg").innerHTML = `<img src="${wilderness.match(/src="([^"]*)" width="250" height="250"/i)[1]}" class="wilderness-mob-img">`;
    return atkLink;
};

async function appWildernessAttack(atkLink,wins,losses,best){

    const attack = await superfetch(atkLink,true);

    if (attack.match(/var successful = 1/i)){
        wins += 1;
        best = 100000000;
        atkLink = await appWildernessLoad();

    } else {
        losses += 1;
        const mobHp = parseInt(attack.match(/var defender_health_start = ([0-9]+)/i)[1]);
        const mobBaseDmgTaken = (attack.match(/defender_taken\[[0-9]+\] = '[0-9]+'/g) || []).reduce((sum, match) => sum + parseInt(match.match(/'([0-9]+)'/)[1]), 0);
        const mobHolyDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'holy'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
        const mobArcnDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'arcane'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
        const mobShadDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'shadow'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
        const mobFireDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'fire'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
        const mobKinkDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'kinetic'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
        const mobChosDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'chaos'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
        const mobRemainingHp = Math.max((mobHp-mobBaseDmgTaken-mobHolyDmgTaken-mobArcnDmgTaken-mobShadDmgTaken-mobFireDmgTaken-mobKinkDmgTaken-mobChosDmgTaken),0);
        const percent = ((mobRemainingHp/mobHp).toFixed(5))*100;
        if (percent < best){
            best = percent;
        };
    };
    document.querySelector("#wildernessWins").value = wins
    document.querySelector("#wildernessLosses").value = losses
    document.querySelector("#wildernessTotal").value = wins+losses
    document.querySelector("#wildernessBest").value = best
    await appWildernessAttack(atkLink,wins,losses,best);
};


async function appSavedRgas(server,serverNo,rgaName,charId){

    document.querySelector("#overlayWidget").innerHTML = `
    <div style="text-align:center;" id="saveRgasContainer">
    <h6>List session ids seperated by commas or paste from OWH</h6><hr>
    <textarea id="sessionsTextArea" class="form-control-new mb-3" style="resize:none;" cols="70" rows="10"></textarea><br>
    <button class="btn-mm" id="saveRgas">SAVE RGAS</button>
    <button class="btn-mm" id="deleteRgas">RESET RGAS</button><hr>
    <span id="hud"></span>
    </div>
    `

    if (GM_getValue('savedRgas').match("option")){
        const storage = GM_getValue('savedRgas')
        const sessions = storage.match(/rg_sess_id=[A-Za-z0-9]+/g).map(i => i.match(/rg_sess_id=([A-Za-z0-9]+)/)[1]);
        document.querySelector("#sessionsTextArea").value = sessions.join(',')
    };

    document.querySelector("#saveRgas").addEventListener('click',saveError);

    const box = document.querySelector("#sessionsTextArea");
    box.addEventListener('keyup', async function(){
        box.value = box.value.replace(/[A-Za-z0-9]+:/g,'').replace(/ /g,'').replace(/[\n\r]/g,',');
        const count = (box.value.match(/\b[a-zA-Z0-9]{32}\b/g) || []).length;

        if (count >= 1){
            document.querySelector("#saveRgas").addEventListener('click',saveRgas);
            document.querySelector("#saveRgas").removeEventListener('click',saveError);
            document.querySelector("#hud").innerHTML = `Found ${count} sessions`
        };

        const characters = box.value.length;
        if (count != (characters+1)/33){
            document.querySelector("#saveRgas").removeEventListener('click',saveRgas);
            document.querySelector("#saveRgas").addEventListener('click',saveError);
            document.querySelector("#hud").innerHTML = `ERROR: Invalid entry`
        };

        if (box.value == ''){
            document.querySelector("#saveRgas").removeEventListener('click',saveRgas);
            document.querySelector("#saveRgas").addEventListener('click',saveError);
            document.querySelector("#hud").innerHTML = ''
        };
    });

    async function saveRgas(){
        document.querySelector("#saveRgasContainer").innerHTML = '<img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="80px" width="80px">'
        const postedRgas = await mmplus(`CustomRGA|rganame|${server}|${box.value}`);
        GM_setValue('savedRgas', postedRgas.replace(/value="home/g,`value="https://${server}.outwar.com/home`));
        await blankOff();
    };

    async function saveError(){
        alert('ERROR: Invalid entry');
    };

    document.querySelector("#deleteRgas").addEventListener('click', function(){
        GM_deleteValue('savedRgas');
        alert('Saved RGAs have been cleared');
        document.querySelector("#sessionsTextArea").value = '';
    });
};


async function appRaidsReport(server,serverNo,rgaName,charId){
    GM_addStyle(`
    img.raidsReportImg{box-shadow: 5px 5px 5px rgba(0, 0, 0, 1);cursor:pointer;transition: .5s ease-out;width:110px;height:110px;border-radius:5px;position:inline-block;margin-bottom:7px;animation: fadeIn 1s ease-in-out forwards;}
    @keyframes fadeIn {from {opacity: 0;} to {opacity: 1;}}
    img.raidsReportImg:hover{filter: saturate(250%);opacity:0.5;}
    div.reportImgDiv{display: inline-block;font-size: 9px;text-align: center;font-family: monospace,monospace;height:130px;width:130px;margin:10px;}
    `)
    document.querySelector("#overlayWidget").innerHTML = `
    <div id="raidsReportDiv" style="height:100%;overflow:auto;text-align:center;">
    <img src="https://studiomoxxi.com/moxximod/loading-gif.gif" style="height:100px;width:100px">
    </div>
    `
    const crewId = document.body.innerHTML.match(/crewid=([0-9]+)/i)[1]
    const raidResults = await superfetch(`crew_raidresults.php?all_results=Display+all+raid+results&crewid=${crewId}`);
    const targetsArray = raidResults.replace(/[\n\r]/g,'').replace(/[:\-]/g, "").match(/[0-9]+ [0-9]+[A-Za-z]+<\/td><td align="left" valign="top">.*?<\/td>/g).map(i => i.match(/<td align="left" valign="top">(.*?)<\/td>/i)[1])
    let uniqueTargets = [...new Set(targetsArray)];
    let imgArray = [];
    for (let i = 0; i < uniqueTargets.length; i++) {
        const godName = uniqueTargets[i]
        const nameTrimmed = godName.replace(/(,.*|of.*|The|the.*)/g, '');
        const regex = new RegExp(`${godName}.*?raidattack\\.php\\?raidid=[0-9]+`)
        const raidId = raidResults.replace(/[\n\r]/g,'').replace(/[:\-]/g, "").match(regex).map(i => i.match(/raidid=([0-9]+)/i)[1]);
        const raid = await superfetch(`raidattack.php?raidid=${raidId}`);
        const raidImg = raid.replace(`<img src="/assets/img/getpoints.webp">`, '').match(/^<img src="([^"]*)">$/im)[1].toString();
        imgArray.push(`<div class="reportImgDiv"><img src="${raidImg}" id="${nameTrimmed.replace(/ /g,'').toLowerCase()}" alt="${godName}" class="raidsReportImg"><br>${nameTrimmed.toUpperCase()}</div>`);
    };
    document.querySelector("#raidsReportDiv").innerHTML = `
    <h6>Which raid target would you like to run a damage report for?</h6><hr>
    ${imgArray.join('')}
    `

    const btnArray = document.querySelectorAll(".raidsReportImg");
    for (let i = 0; i < btnArray.length; i++) {
        const btn = btnArray[i]
        const id = btn.outerHTML.match(/id="([^"]*)"/i)[1]
        document.querySelector(`#${id}`).addEventListener('click',async function(){
            const alt = btn.outerHTML.match(/alt="([^"]*)"/i)[1]
            const regex = new RegExp(`<td align="left" valign="top">${alt}<\/td>.*?raidid=[0-9]+">`,'g')
            const raidsArray = raidResults.replace(/[\n\r]/g,'').replace(/[:\-]/g, "").match(regex).map(i => i.match(/raidid=([0-9]+)/i)[1]);
            mmplus(`RaidsReport|rganame|${server}|${raidsArray.toString()}`);
            await blankOff();
        });
    };
};


async function appItemAnalyzer(server,serverNo,rgaName,charId){

    document.querySelector("#overlayWidget").innerHTML = `
    <div id="itemStorageDiv" style="text-align:center;height:100%;overflow:auto;">
    <img src="https://studiomoxxi.com/moxximod/loading-gif.gif" style="height:100px;width:100px">
    </div>
    `

    const charDropdown = document.body.innerHTML.replace(/[\n\r]/g,'').match(/<optgroup label="My Characters">.*?<option value="0">--Change Server--<\/option>/i)
    const charIdArray = charDropdown.toString().match(/value="[0-9]+"/g).map(match => match.match(/[0-9]+/)[0]).slice(0, -1);

    let tableData = [];
    const inventory = async (id) => {

        const fetchEq = await superfetch(`equipment?suid=${id}`);
        const itemsId = fetchEq.replace(/[\n\r]/g,'').replace(/<div style="position:absolute; left:10px; top:346px; width:32px; height:32px;text-align:center">.*/i,'').match(/event,'([0-9]+)'/g);

        if (itemsId){
            for (let i = 0; i < itemsId.length; i++) {
                const iid = itemsId[i].match(/[0-9]+/i)[0];
                const item = await superfetch(`item_rollover.php?id=${iid}`);
                const parse = item.match(/color:#([A-Za-z0-9]+)" align="left">(.*?)<\/td>/i)
                const name = parse[2]
                const gems = 4-(item.match(/\/images\/gemslot2\.jpg/) ? item.match(/\/images\/gemslot2\.jpg/g).length : 0);
                const augs = item.match(/img width="9" style="border:1px solid #666666;margin:2px;"/) ? item.match(/img width="9" style="border:1px solid #666666;margin:2px;"/g).length : 0;
                const open = item.match(/\/images\/augslot\.jpg/) ? item.match(/\/images\/augslot\.jpg/g).length : 0;
                const atk = parseInt((item.replace(/(\([^)]*\)|<[^>]*>|,|\s)/g, '').match(/\+([0-9]+)ATK/i) || [0,0])[1])
                const hp = parseInt((item.replace(/(\([^)]*\)|<[^>]*>|,|\s)/g, '').match(/\+([0-9]+)HP/i) || [0,0])[1])
                const maxrage = parseInt((item.replace(/(\([^)]*\)|<[^>]*>|,|\s)/g, '').match(/\+([0-9]+)maxrage/i) || [0,0])[1])

                if (gems != 4){
                    const rarity = parse[1];
                    const upgrades = await info("Cost to Gem");
                    const cost = upgrades[rarity][gems];
                    tableData.push(`
                        <tr id="row${iid}">
                        <td><a id="delete${iid}" href="javascript:void(0);">&#x2718;</a></td>
                        <td><input type="checkbox" id="check${iid}"></td>
                        <td><a href="blacksmith?itemid=${iid}&suid=${id}" target="_blank" id="iid${iid}" class="itemLink">${name}</a></td>
                        <td>${gems}</td>
                        <td>${augs+open}</td>
                        <td><a href="augmentequip?suid=${id}" target="_blank">${open}</a></td>
                        <td>${Math.ceil((atk+hp)*0.15/cost)}</td>
                        <td>${Math.ceil(maxrage*0.15/cost)}</td>
                        </tr>
                    `);
                };
            };
        };
    };
    await Promise.all(charIdArray.map(inventory));

    document.querySelector("#itemStorageDiv").innerHTML = `
    <table id="inventory" class="table table-striped sortable" style="text-align:left">
    <thead><tr>
    <th><img src="images/questwiki.jpg" onmouseover="statspopup(event,'Click to delete the row')" onmouseout="kill()" style="margin-bottom:5px;"></th>
    <th><img src="images/questwiki.jpg" onmouseover="statspopup(event,'Mark completed. Will auto-check if you click on the item name')" onmouseout="kill()" style="margin-bottom:5px;"></th>
    <th>Item</th>
    <th>Gems</th>
    <th>Aug Slots</th>
    <th>Open Augs</th>
    <th>ATK+HP Gained per Point<br>with one gem added</th>
    <th>Max Rage gained per Point<br>with one gem added</th>
    </tr></thead>
    <tbody>${tableData.join('')}</tbody>
    </table>
    `

    const itemLinks = document.querySelectorAll(".itemLink")
    for (let i = 0; i < itemLinks.length; i++) {
        const link = itemLinks[i]
        const iid = link.outerHTML.match(/id="iid([0-9]+)"/)[1]
        document.querySelector(`#iid${iid}`).addEventListener('click',function(){
            document.querySelector(`#check${iid}`).checked = true;
        });
        document.querySelector(`#delete${iid}`).addEventListener('click',function(){
            document.querySelector(`#row${iid}`).remove();
        });
    };

    sortableTables();
};


async function appMobAttacker(server,serverNo,rgaName,charId){

    GM_addStyle(`
        #mobAtkWidget {text-align:center;}
        .mob-div > input {width: 100px;font-size: 10px;padding: 5px;margin:5px;}
        .mob-div > img {height: 100px;width: 100px;border-radius: 15px;border:2px SOLID #313131;cursor: pointer;margin:5px;}
        .mob-div {display: inline-block;margin-bottom: 1rem;font-family: monospace;font-size: 12px;text-align: center;}
        #authSlider{display:none;}
        .mob-selected{border: 3px #00CC00 SOLID !important;padding: 3px !important;animation: mob-selected 1s infinite;}
        @keyframes mob-selected{0% {filter: saturate(100%);} 50% {filter: saturate(250%); } 100% {filter: saturate(100%);}}
    `)

    document.querySelector("#overlayWidget").innerHTML = `
        <div id="mobAtkWidget">
        <h4>CREATING BATTLE PLAN</h4><br>
        <img src="https://studiomoxxi.com/moxximod/loading-gif.gif" style="height:100px;width:100px">
        </div>
    `

    if (GM_getValue('savedRgas') != "no sessions saved" && GM_getValue('savedRgas')){
        const rgas = GM_getValue('savedRgas').match(/rg_sess_id=[A-Za-z0-9]+&suid=[0-9]+&serverid=[0-9]+/g);
        await loadChars(rgas);

    } else {
        await loadChars([`rg_sess_id=${rgaName}&suid=${charId}&serverid=${serverNo}`]);
    };

    async function loadChars(rgas){
        const strings = []
        const parseChars = async (string) => {

            const session = string.match(/rg_sess_id=([A-Za-z0-9]+)/)[1];
            const auth = await mmplus(`AuthCheck|${session}`);

            if (!auth.match("Full")){
                return;
            };

            const startingId = string.match(/suid=([0-9]+)/i)[1];
            const ajax = await superfetch(`ajax/accounts.php?t_serv=${serverNo}&${string}`);
            const chars = ajax.match(/"id":"[0-9]+"/g).map(id => id.match(/[0-9]+/i));
            chars.forEach(async char => {
                strings.push(string.replace(startingId,char));
            });
        };
        await Promise.all(rgas.map(parseChars));

        let mobs = {
            "seeping":{charNames:[],charIds:[],quest:2092,id:4379,mobName:'SEEPING',roomNum:32876,mobImg:'images/mobs/chaosgolem5.jpg'},
            "deluged":{charNames:[],charIds:[],quest:2093,id:4380,mobName:'DELUGED',roomNum:32878,mobImg:'images/mobs/chaosgolem2.jpg'},
            "volatile":{charNames:[],charIds:[],quest:2094,id:4381,mobName:'VOLATILE',roomNum:32877,mobImg:'images/mobs/chaosgolem4.jpg'},
            "lorren3":{charNames:[],charIds:[],quest:1532,id:3731,mobName:'PERPETUAL',roomNum:26616,mobImg:'images/mobs/mobc62.jpg'},
            "aestor3":{charNames:[],charIds:[],quest:1891,id:3920,mobName:'ROENOV',roomNum:27528,mobImg:'images/mobs/mobm93.jpg'},
            "aestor4":{charNames:[],charIds:[],quest:1916,id:3921,mobName:'SKITTOR',roomNum:27527,mobImg:'images/mobs/mobz2.jpg'},
            "aestor5":{charNames:[],charIds:[],quest:1917,id:3922,mobName:'ERGON',roomNum:27526,mobImg:'images/mobs/mobi18.jpg'},
            "ferocity":{charNames:[],charIds:[],quest:2035,id:4038,mobName:'ULKOR',roomNum:28122,mobImg:'images/mobs/mobc48.jpg'},
            "class":{charNames:[],charIds:[],quest:2033,id:4035,mobName:'YOUNIS',roomNum:28113,mobImg:'images/mobs/mobk9.jpg'},
            "hovok":{charNames:[],charIds:[],quest:0,id:4046,mobName:'HOVOK',roomNum:28123,mobImg:'images/mobs/mobm91.jpg'},
            "rank5":{charNames:[],charIds:[],quest:1941,id:3931,mobName:'DARKLORD',roomNum:27608,mobImg:'images/mobs/moba76.jpg'},
            "rank10":{charNames:[],charIds:[],quest:1942,id:3932,mobName:'FIREPRIEST',roomNum:27609,mobImg:'images/mobs/mobh85.jpg'},
            "rank15":{charNames:[],charIds:[],quest:1943,id:3933,mobName:'ENCHANTER',roomNum:27632,mobImg:'images/mobs/mobi58.jpg'},
            "rank20":{charNames:[],charIds:[],quest:1944,id:3934,mobName:'DIVINER',roomNum:27633,mobImg:'images/mobs/mobz78.jpg'},
            "normok2":{charNames:[],charIds:[],quest:2047,id:4050,mobName:'CORVOK',roomNum:27624,mobImg:'images/mobs/mobd12.jpg'},
            "invader":{charNames:[],charIds:[],quest:2359,id:5274,mobName:'INVADER',roomNum:37878,mobImg:'images/mobs/mobh31.png'},
            "thief":{charNames:[],charIds:[],quest:0,id:3519,mobName:'THIEF',roomNum:26199,mobImg:'images/mobs/mobz59.jpg'},
            "betrayer":{charNames:[],charIds:[],quest:0,id:3520,mobName:'BETRAYER',roomNum:26200,mobImg:'images/mobs/mobz41.jpg'},
            "plant":{charNames:[],charIds:[],quest:0,id:4392,mobName:'PLANT',roomNum:31686,mobImg:'images/mobs/woodsplant.jpg'},
            "gveiled":{charNames:[],charIds:[],quest:0,id:5301,mobName:'GUARD',roomNum:42619,mobImg:'images/mobs/veiledguard.png'},
            "kveiled":{charNames:[],charIds:[],quest:0,id:5302,mobName:'KEEPER',roomNum:42620,mobImg:'images/mobs/veiledkeeper.png'},
            "aprecision":{charNames:[],charIds:[],quest:0,id:5481,mobName:'PRECISION',roomNum:0,mobImg:'images/mobs/owmob784.png'},
            "dprecision":{charNames:[],charIds:[],quest:0,id:5482,mobName:'PRECISION',roomNum:0,mobImg:'images/mobs/owmob176.png'},
            "vprecision":{charNames:[],charIds:[],quest:0,id:5483,mobName:'PRECISION',roomNum:0,mobImg:'images/mobs/owmob1210b.png'}
        };

        const circArray = [];
        const oorArray = [];

        async function scanChars(string){

            const profile = await superfetch(`profile?${string}`);

            const kbp = await superfetch(`ajax/backpackcontents.php?tab=key&${string}`);
            const veiledteleporter = kbp.match(/data-name="Veiled Teleporter"/i);
            const veiledidol = kbp.match(/data-name="Veiled Idol"/i);
            const groveinsignia = kbp.match(/data-name="Grove Insignia"/i);

            const id = string.match(/rg_sess_id=([A-Za-z0-9]+)/i)[1] + '&' + string.match(/suid=([0-9]+)/i)[1];
            const name = profile.match(/<font size="3">(.*?)<\/font>/i)[1];
            const rage = parseInt(profile.replace(/[\n\r,]/g, '').match(/<span class="toolbar_rage">(.*?)<span>/i)[1]);
            const circ = profile.match(/Circumspect/i) ? "Yes" : "No";
            const factionMatch = profile.match(/<font size="1">FACTION<\/font><\/b><\/td>\n.*?([A-Za-z]+) \((.*?)\)/i)
            const faction = factionMatch[1];
            const loyalty = factionMatch[2] === "" ? 0 : parseInt(factionMatch[2]);

            if (rage < 1000){
                oorArray.push(name);

            } else {
                for (const mobName of Object.keys(mobs)) {
                    const mob = mobs[mobName];

                    const quest = mob.quest == 0 ? "noquest" : await superfetch(`quest_info.php?questnum=${mob.quest}&${string}`);

                    if (quest != "error"){

                        if (mobName == "hovok"){
                            const quantum = await superfetch(`quest_info.php?questnum=${2038}&${string}`);
                            const explosive = await superfetch(`quest_info.php?questnum=${2039}&${string}`);
                            const violent = await superfetch(`quest_info.php?questnum=${2040}&${string}`);
                            const onslaught = await superfetch(`quest_info.php?questnum=${2041}&${string}`);
                            if (quantum != "error" || explosive != "error" || violent != "error" || onslaught != "error"){
                                const search = await superfetch(`mob_search.php?target=${mob.id}&${string}`);
                                if (search.match(/Quest help activated/i)){
                                    mob.charNames.push(name);
                                    mob.charIds.push(id);
                                };
                            };

                        } else if (mobName.match("veiled")){
                            if (mobName == "gveiled" && veiledteleporter){
                                const search = await superfetch(`mob_search.php?target=${mob.id}&${string}`);
                                if (search.match(/Quest help activated/i)){
                                    mob.charNames.push(name);
                                    mob.charIds.push(id);
                                };
                            } else if (mobName == "kveiled" && veiledidol){
                                const search = await superfetch(`mob_search.php?target=${mob.id}&${string}`);
                                if (search.match(/Quest help activated/i)){
                                    mob.charNames.push(name);
                                    mob.charIds.push(id);
                                };
                            };

                        } else if (mobName.match("precision")){
                            if (mobName == "aprecision" && faction == "Alvar" && loyalty >= 1 && groveinsignia){
                                const search = await superfetch(`mob_search.php?target=${mob.id}&${string}`);
                                if (search.match(/Quest help activated/i)){
                                    mob.charNames.push(name);
                                    mob.charIds.push(id);
                                };
                            } else if (mobName == "dprecision" && faction == "Delruk" && loyalty >= 1 && groveinsignia){
                                const search = await superfetch(`mob_search.php?target=${mob.id}&${string}`);
                                if (search.match(/Quest help activated/i)){
                                    mob.charNames.push(name);
                                    mob.charIds.push(id);
                                };
                            } else if (mobName == "vprecision" && faction == "Vordyn" && loyalty >= 1 && groveinsignia){
                                const search = await superfetch(`mob_search.php?target=${mob.id}&${string}`);
                                if (search.match(/Quest help activated/i)){
                                    mob.charNames.push(name);
                                    mob.charIds.push(id);
                                };
                            };

                        } else {
                            const search = await superfetch(`mob_search.php?target=${mob.id}&${string}`);
                            if (search.match(/Quest help activated/i)){
                                mob.charNames.push(name);
                                mob.charIds.push(id);
                            };
                        };
                    };
                };
            };
        };
        await Promise.all(strings.map(scanChars));

        const divs = [];
        if (oorArray.length > 0){
            divs.push(`<div class="mob-div"><img src="images/rfury.jpg"><br>OUT OF RAGE<br>${oorArray.length} attackers<br><input type="text" class="form-control-new" value="${oorArray.join(',')}"></div>`);
        };
        for (const mobName of Object.keys(mobs)) {
            const mob = mobs[mobName]
            if (mob.charIds.length > 0){
                divs.push(`
                    <div class="mob-div">
                    <img src="${mob.mobImg}" class="mob-img" name="${mob.mobName.toLowerCase()}" alt="${mob.roomNum}|${mob.charIds.join(',')}"><br>
                    ${mob.mobName}<br>
                    ${mob.charIds.length} attackers<br>
                    <input type="text" class="form-control-new list-of-chars" value="${mob.charNames.join(',')}">
                    </div>
                `);
            };
        };

        document.querySelector("#mobAtkWidget").innerHTML = `
            <h4>CLICK MOB IMAGES TO SELECT TARGETS</h4>
            <div style="background-color:#000000;padding:10px;border-radius:10px;box-shadow:5px 5px 5px rgba(0, 0, 0, 1);margin-bottom:1rem;">
            ${divs.join('')}
            </div>
            <button class="btn-mm" id="attackMobs">ATTACK SELECTED MOBS</button>
        `

        const textBoxes = document.querySelectorAll(".list-of-chars");
        textBoxes.forEach(i => {
            i.addEventListener('click',function(){
                i.select();
            });
        });

        const mobPics = document.querySelectorAll(".mob-img");
        mobPics.forEach(i => {
            i.addEventListener('click',function(){
                i.classList.toggle('mob-selected');
            });
        });

        document.querySelector("#attackMobs").addEventListener('click',async function(){
            const cmd = [`NewMobAtk|rganame|${server}|`];
            const selectedMobs = document.querySelectorAll(".mob-selected");
            selectedMobs.forEach(i => {
                const mobName = i.outerHTML.match(/name="([^"]*)"/i)[1];
                const selectedChars = i.outerHTML.match(/alt="([^"]*)"/i)[1];
                cmd.push(`${mobName}|${selectedChars.replace(/amp;/g,'')}`);
            });
            document.querySelector("#attackMobs").remove();
            await mmplus(cmd.join("\n"));
            GM_addStyle('#authSlider{display:revert !important;}');
        });
    };
};


async function appGladiator(server,serverNo,rgaName,charId){

    GM_addStyle(`
        div.app-glad-div{ display:flex; height:96%; justify-content:center; }
        div.app-glad-div-outer{ height:100%; }
        div.app-glad-div-inner{ background-color:#060818; border-radius:10px !important; color:#FFFFFF; padding:20px; margin:1rem;box-shadow:0 5px 5px 0 rgba(0,0,0,1);transition: height 0.5s ease;}
        div.glad-hide{opacity:0;transition: opacity 0.5s ease;}
        img.glad-mob-img{ width:150px; height:150px; border-radius:10px; margin-bottom:1rem;cursor:pointer;box-shadow:0 5px 5px 0 rgba(0,0,0,1);}
        #gladRankings{height:100%;overflow:auto;flex:1;margin-bottom:1rem;box-shadow:0 5px 5px 0 rgba(0,0,0,1);}
        #rankingsTable{text-align:left;}
        input.glad-txt{background:#FFFFFF !important;color:#000000 !important;opacity:1 !important;}
        div.glad-skills > div > img {width:25px;height:25px;margin:4px;border-radius:10px;box-shadow:0 3px 3px 0 rgba(0,0,0,0.5);background:#000000;transition:0.25s ease-out;}
        #available,#active,#missing{margin-top:0.5rem;}
        img.glad-caster-selected{border:2px #00CC00 SOLID !important;padding:3px !important;}
    `)

    const kbp = await superfetch('ajax/backpackcontents.php?tab=key');
    const admission = kbp.match(/data-name="Gladiator Arena Admission"/i);

    if (admission){
        const ajax = await superfetch('ajax_changeroomb');
        const room = ajax.match(/"curRoom":"([0-9]+)"/i)[1];
        if (room == "28031"){
            document.querySelector("#overlayWidget").innerHTML = `
            <div class="app-glad-div">
            <div class="app-glad-div-outer" style="flex:1">
            <div class="app-glad-div-inner list-group-item" style="height:100%;width:200px;text-align:center;">
            <h5>Available Glads<h5><br>
            <div id="gladAvailable"><img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="80px" width="80px"></div>
            </div>
            </div>
            <div class="app-glad-div-outer" style="flex:2">
            <div class="app-glad-div-inner glad-hide list-group-item" style="height:100%;text-align:center;display:flex;flex-direction:column;">
            <h5>Current Rankings</h5><br>
            <div id="myRank" class="mb-3"></div>
            <div id="gladRankings"><img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="80px" width="80px"></div>
            <button class="btn-mm" id="refreshRankings">REFRESH RANKINGS</button>
            </div>
            </div>
            <div class="app-glad-div-outer" id="skillsRight" style="flex:3">
            <div class="app-glad-div-inner glad-hide glad-skills list-group-item">
            <h5>Active Skills & Potions</h5>
            <div id="active"><img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="40px" width="40px"></div>
            </div>
            <div class="app-glad-div-inner glad-hide glad-skills list-group-item">
            <h5>Available Skills & Potions</h5>
            <div id="available" class="mb-3"><img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="40px" width="40px"></div>
            </div>
            <div class="glad-skills glad-hide" style="margin-left:1rem;margin-top:1rem;">
            <button class="btn-mm" id="castSelected">CAST SELECTED</button>
            <button class="btn-mm" id="refreshAll">REFRESH</button>
            <button class="btn-mm" id="castBoosts">CAST BOOSTS</button>
            </div>
            <div class="app-glad-div-inner glad-hide glad-skills list-group-item">
            <h5>Missing Potions</h5>
            <div id="missing"><img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="40px" width="40px"></div>
            </div>
            <div class="app-glad-div-inner glad-hide glad-skills list-group-item">
            <div class="form-control-new" style="padding:1rem;opacity:1 !important;">
            Stop after <input id="stopAttacks" type="number" class="form-control-new glad-txt" style="width:70px;" autocomplete="off"> attacks or achieving <input id="stopDamage" type="number" class="form-control-new glad-txt" autocomplete="off" style="width:140px;"> damage
            </div>
            </div>
            <div class="glad-skills glad-hide" style="margin-left:1rem;margin-top:1rem;">
            <button id="atkGlad" class="btn-mm"></button>
            </div>
            </div>
            </div>
            `

            const gladTxt = await superfetch('gladiator');
            const parser = new DOMParser();
            const gladHtml = parser.parseFromString(gladTxt, 'text/html');
            const divQuest = gladHtml.querySelectorAll(".divQuest");

            const gladNames = [];
            divQuest.forEach(div => {
                if (div.innerHTML.match('Will retreat in')){
                    gladNames.push(div.innerHTML.match(/<h1>(.*?)<\/h1>/i)[1]);
                };
            });
            const mobArray = [];
            const gladiators = async (name) => {
                const ajax = await superfetch('ajax_changeroomb');
                const regex = new RegExp(`"name":"${name}","level":"[0-9]+","rage":"[0-9]+","h":"[^"]*","encid":"[^"]*","mobId":"[0-9]+","spawnId":"[0-9]+","image":"[^"]*"`,'i');
                const string = ajax.match(regex).toString();
                const mobImg = 'images/' + string.match(/"image":"([^"]*)"/i)[1];
                const spawnId = string.match(/"spawnId":"([0-9]+)"/)[1]
                const mobId = string.match(/"mobId":"([0-9]+)"/i)[1]
                mobArray.push(`<img src="${mobImg}" class="glad-mob-img" id="${spawnId}" alt="${mobId}" name="${name}">`);
            };
            await Promise.all(gladNames.map(gladiators))
            document.querySelector("#gladAvailable").innerHTML = mobArray.join('<br>')

            const allGlads = document.querySelectorAll(".glad-mob-img");
            allGlads.forEach(img => {
                img.addEventListener('click', async function(){

                    GM_addStyle('div.glad-hide{opacity:1 !important;}');
                    const spawnId = img.outerHTML.match(/id="([0-9]+)"/i)[1];
                    const mobId = img.outerHTML.match(/alt="([0-9]+)"/i)[1];
                    const mobName = img.outerHTML.match(/name="([^"]*)"/i)[1];

                    document.querySelector("#atkGlad").outerHTML = `<button id="atkGlad" class="btn-mm">ATTACK ${mobName.toUpperCase()}</button>`

                    await appGladiatorGetRankings(mobId,charId);

                    await appGladiatorColumnRight(server,charId);

                    await appGladiatorSelect();

                    document.querySelector("#refreshRankings").addEventListener('click', async function(){
                        document.querySelector("#gladRankings").innerHTML = `<img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="80px" width="80px">`
                        await appGladiatorGetRankings(mobId,charId);
                    });

                    document.querySelector("#atkGlad").addEventListener('click', async function(){
                        const stopAttacks = document.querySelector("#stopAttacks").value.replace(/,/g,'');
                        const stopDamage = document.querySelector("#stopDamage").value.replace(/,/g,'');
                        if (isNaN(stopAttacks) || isNaN(stopDamage) || stopAttacks == '' || stopDamage == ''){
                            alert('ERROR: Please enter target amounts for number of attacks and damage');
                        } else {
                            await mmplus(`MultiMobAtk|rganame|${server}|${charId}|${stopAttacks}|${spawnId}|${stopDamage}`);
                        };
                    });
                });
            });

            document.querySelector("#castBoosts").addEventListener('click', async function(){
                const confirmBoost = confirm('Casting boosts will cost 25 points');
                if (confirmBoost){
                    await superfetch('userbuff.php?castboost=1',true);
                    await superfetch('userbuff.php?castboost=1',true);
                    await superfetch('userbuff.php?castboost=1',true);
                    await superfetch('userbuff.php?castboost=1',true);
                    await superfetch('userbuff.php?castboost=1',true);
                    await appGladiatorColumnRight(server,charId);
                };
            });

            document.querySelector("#castSelected").addEventListener('click', async function() {
                const selectedImages = document.querySelector("#available").querySelectorAll("img.glad-caster-selected");
                const imgIds = Array.from(selectedImages).map(img => img.id);
                await mmplus(`Cast|rganame|${server}|${charId}|${imgIds.join(',')}`);
            });

            document.querySelector("#refreshAll").addEventListener('click', async function(){
                document.querySelector("#active").innerHTML = `<img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="40px" width="40px">`
                document.querySelector("#available").innerHTML = `<img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="40px" width="40px">`
                document.querySelector("#missing").innerHTML = `<img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="40px" width="40px">`
                await appGladiatorColumnRight(server,charId);
            });
        } else {
            document.querySelector("#overlayWidget").innerHTML = `<center><h3>Must be in the Gladiator Arena</h3><hr><button class="btn-mm" id="goTo28031">GO TO RM 28031</button></center>`
            document.querySelector("#goTo28031").addEventListener('click', async function(){
                await goToRoomNum(server,charId,28031);
            });
        };

    } else {
        document.querySelector("#overlayWidget").innerHTML = `<center><h3>Missing Gladiator Admission key</h3><hr><button class="btn-mm" id="goTo50">GO TO RM 50</button></center>`
        document.querySelector("#goTo50").addEventListener('click', async function(){
            await goToRoomNum(server,charId,50);
        });
    };
};


async function appGladiatorGetRankings(mobId,charId){
    const gladPageTxt = await superfetch(`gladiator?mobid=${mobId}`,true);
    const parser = new DOMParser();
    const gladPageHtml = parser.parseFromString(gladPageTxt, 'text/html');
    const divs = Array.from(gladPageHtml.querySelectorAll('.mt-lg-0 .grid-item')).map(div => div.innerHTML);
    let columns = divs.indexOf("Atks") + 1;

    const rankArrays = [];
    let tempArray = [];
    divs.forEach((div, index) => {
        tempArray.push(div);

        if ((index + 1) % (columns) === 0) {
            rankArrays.push(tempArray);
            tempArray = [];
        }
    });

    const rows = [];
    let myRow = ['No attacks found'];
    rankArrays.forEach(col => {
        let row = ''
        for (let i = 0; i < columns; i++) {
            row += `<td>${col[i]}</td>`
        };
        rows.push(`<tr>${row}</tr>`);

        if (col.toString().match(`id=${charId}`)){
            myRow = col.slice(0, -1);
        };
    });
    document.querySelector("#gladRankings").innerHTML = `
        <table id="rankingsTable" class="table table-striped">
        ${rows.join('').replace(/<a.*?>/g,'')}
        </table>
    `
    document.querySelector("#myRank").innerHTML = `
        <div class="form-control-new" style="padding:1rem;opacity:1 !important;width:100%;">
        <table class="table table-striped"><tr><td>
        ${myRow.join('</td><td>').replace(/<a.*?>/g,'')}
        </td></tr></table>
        </div>
    `
};


async function appGladiatorColumnRight(server,charId,spawnId){

    const profile = await superfetch('profile',true);
    let allCastAndBp = [];

    const allCast = profile.match(/<img align="absmiddle" border="0" src="[^"]*" hspace="2" width="25" height="25" alt=".*?" ONMOUSEOVER="popup\(event,'.*?',[0-9]+\)" ONMOUSEOUT="kill\(\)">/g) || [];

    for (let i = 0; i < allCast.length; i++) {
        allCastAndBp.push(allCast[i].match(/src="([^"]*)"/)[1].replace(/\/skills\/\.\./,'').replace(/ /g,'%20'));
    };

    let skillsArray = [];
    let skillIdArray = [];

    const classEndpoints = ['cast_skills.php','cast_skills.php?C=4','cast_skills.php?C=5','cast_skills.php?C=6','cast_skills.php?C=7']
    const skillClasses = await Promise.all(classEndpoints.map(endpoint => fetch(endpoint).then(res => res.text())));
    for (let i = 0; i < skillClasses.length; i++) {
        const skillIds = skillClasses[i].match(/loadskill\([0-9]+\)/g) || [];
        for (let i = 0; i < skillIds.length; i++) {
            skillIdArray.push(skillIds[i].match(/[0-9]+/i))
        };
    };
    const skillInfos = await Promise.all(skillIdArray.map(endpoint => fetch(`skills_info.php?id=${endpoint}`).then(res => res.text())));
    for (let i = 0; i < skillInfos.length; i++) {
        const info = skillInfos[i]
        if (info.match(`<input type="submit" name="cast" class="btn btn-primary" value="Cast Skill">`)){
            const skillName = info.match(/<h5>(.*?)<\/h5>/i)[1]
            const skillImg = info.match(/style="[^"]*" src="([^"]*)"/i)[1]
            const skillId = info.match(/value="([0-9]+)"/i)[1]
            const skillText = info.replace(/'/g,'').match(/<h5>.*[\n\r](.*)<\/div>/)[1]
            if (!profile.match(skillImg)){
                skillsArray.push(`<img src="${skillImg}" class="castable cast-skill" id="${skillId}" onmouseover="statspopup(event,'<b>${skillName}</b><br>${skillText}')" onmouseout="kill()">`)
            };
        };
    };

    const potionBp = await fetch('ajax/backpackcontents.php?tab=potion').then(res => res.text());
    const allPots = potionBp.match(/data-iid="[0-9]+" id="[^"]*" class="[^"]*" src="[^"]*" alt=".*?"/g);
    for (let i = 0; i < allPots.length; i++) {
        const potion = allPots[i]
        const potId = potion.match(/data-iid="([0-9]+)"/i)[1]
        const potImg = potion.match(/src="([^"]*)"/i)[1]
        const potName = potion.match(/alt="([^"]*)"/i)[1]
        if (!profile.replace(/skills\/\.\.\//g,'').match(potImg)){
            skillsArray.push(`<img src="${potImg}" name="${potName}" class="castable cast-potion" id="${potId}" onmouseover="itempopup(event,'${potId}')" onmouseout="kill()">`);
            allCastAndBp.push(potImg.replace(/ /g,'%20'));
        };
    };

    const infoAllPots = await info("All Potions")
    const missingPotsArray = [];
    for (let i = 0; i < infoAllPots.length; i++) {
        const potName = infoAllPots[i][0];
        const potImg = infoAllPots[i][1];
        if (!allCastAndBp.includes(potImg) && !potImg.match(/images\/items\/icon_vial_[A-Za-z0-9]+\.jpg/i)) {
            missingPotsArray.push(`<img src="${potImg}" onmouseover="popup(event,'${potName}')" onmouseout="kill()">`)
        };
    };
    document.querySelector("#active").innerHTML = allCast.join('').replace(/skills\/\.\.\//g,'');
    document.querySelector("#available").innerHTML = skillsArray.join('');
    document.querySelector("#missing").innerHTML = missingPotsArray.join('');
};


async function appGladiatorSelect(){

    const warning = ['/images/rfury.jpg','/images/items/haste.png','/images/items/sfury.jpg','/images/items/whiskeypot.png','/images/items/itemz80.gif','/images/items/pvpimmune.jpg'];

    $('#available').on('click','img',(function() {

        if (this.outerHTML.match(/name="([^"]*)"/i)){
            const img = this.outerHTML.match(/src="([^"]*)"/i)[1];
            const name = this.outerHTML.match(/name="([^"]*)"/i)[1];
            const hasSelectedClass = $(this).hasClass('glad-caster-selected');
            if (warning.includes(img) && !hasSelectedClass){
                const confirmSelect = confirm(`Are you sure you want to select ${name}?`);
                if (confirmSelect){
                    $(this).toggleClass("glad-caster-selected");
                };
            } else {
                $(this).toggleClass("glad-caster-selected");
            };

        } else {
            $(this).toggleClass("glad-caster-selected");
        };
    }));
};


async function appMobRaider(server,serverNo,rgaName,charId){

    const overlayWidget = document.querySelector("#overlayWidget");
    const height = overlayWidget.offsetHeight;
    GM_addStyle(`
        div.mobImgDiv {display: inline-block;font-size: 10px;text-align: center;font-family: monospace,monospace;height: 115px;width: 115px;margin-left:1px;margin-right:1px;margin-bottom:20px;}
        img.mobImg {box-shadow: 5px 5px 5px rgba(0, 0, 0, 1);cursor: pointer;width: 110px;height: 110px;border-radius: 5px;margin-bottom: 2px;}
        #topDiv {width:100%;overflow:auto;background-color:#000000;padding:10px;text-align:center;box-shadow: 5px 5px 5px rgba(0, 0, 0, 1);margin-bottom:1rem;}
        div.dataDivs {text-align:left;overflow:auto;height:${height-245}px;display:inline-block;margin:10px;padding:20px;background-color:#000000;border-radius:10px;box-shadow: 5px 5px 5px rgba(0, 0, 0, 1);width:285px;}
        #bottomDiv {text-align:center;}
        button.btn-mm{font-size:12px;padding:0.5rem;}
        #selectedRaidMob{animation: tileanimate 2s infinite;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);}
        @keyframes tileanimate{0% {filter: saturate(100%);} 50% {filter: saturate(250%); } 100% {filter: saturate(100%);}}
    `);


    document.querySelector("#overlayWidget").innerHTML = `
    <div class="innerDivs" id="topDiv">
    <div class="mobImgDiv"><img id="veiled" alt="3" class="mobImg" src="/images/mobs/veiledchest.png">Locker</div>
    <div class="mobImgDiv"><img id="morrik" alt="10" class="mobImg" src="images/mobs/mobi57.jpg">Morrik</div>
    <div class="mobImgDiv"><img id="grouz" alt="10" class="mobImg" src="images/mobs/moba56.jpg">Grouz</div>
    <div class="mobImgDiv"><img id="crawling" alt="1" class="mobImg" src="images/mobs/arsetmob1.gif">Crawling</div>
    <div class="mobImgDiv"><img id="conductor" alt="30" class="mobImg" src="images/mobs/mobk50.jpg">Conductor</div>
    <div class="mobImgDiv"><img id="demonic" alt="30" class="mobImg" src="images/mobs/mobl83.jpg"><br>Demonic</div>
    <div class="mobImgDiv"><img id="elexocutioner" alt="30" class="mobImg" src="images/mobs/moba87.jpg">Elexocutioner</div>
    <div class="mobImgDiv"><img id="chaosele" alt="5" class="mobImg" src="images/mobs/chaosgolem3.jpg">Chaotic Elemental</div>
    <div class="mobImgDiv"><img id="badge1" alt="10" class="mobImg" src="images/mobs/mobc86.jpg">Sharkrat</div>
    <div class="mobImgDiv"><img id="badge2" alt="10" class="mobImg" src="images/mobs/mobl29.jpg">Vullianne</div>
    <div class="mobImgDiv"><img id="badge3" alt="10" class="mobImg" src="images/mobs/mobd23.jpg">Kaggar</div>
    <div class="mobImgDiv"><img id="badge4" alt="10" class="mobImg" src="images/mobs/mobzz49.gif">Cheigon</div>
    <div class="mobImgDiv"><img id="badge5" alt="10" class="mobImg" src="images/mobs/mobg13.jpg">Zyssi</div>
    <div class="mobImgDiv"><img id="eth1" alt="5" class="mobImg" src="images/mobs/arraid1.jpg">Ethereal Priest</div>
    <div class="mobImgDiv"><img id="eth2" alt="5" class="mobImg" src="images/mobs/arsetraid2.jpg">Ethereal Serpent</div>
    <div class="mobImgDiv"><img id="eth3" alt="5" class="mobImg" src="images/mobs/arraid3.jpg">Ethereal Steed</div>
    <div class="mobImgDiv"><img id="eth4" alt="5" class="mobImg" src="images/mobs/arraid4.jpg">Ethereal Sorcerer</div>
    <div class="mobImgDiv"><img id="eth5" alt="5" class="mobImg" src="images/mobs/arraid5.jpg">Ethereal Doomlord</div>
    <div class="mobImgDiv"><img id="novice" alt="5" class="mobImg" src="images/mobs/mobf28.jpg">Novice Protector</div>
    <div class="mobImgDiv"><img id="great" alt="5" class="mobImg" src="images/mobs/mobb10.jpg">Great Protector</div>
    <div class="mobImgDiv"><img id="grand" alt="5" class="mobImg" src="images/mobs/mobe57.jpg">Grand Protector</div>
    <div class="mobImgDiv"><img id="rival1" alt="5" class="mobImg" src="images/mobs/pathraid1.gif">Rank 1 Rival</div>
    <div class="mobImgDiv"><img id="rival2" alt="5" class="mobImg" src="images/mobs/pathraid2.gif">Rank 2 Rival</div>
    <div class="mobImgDiv"><img id="rival3" alt="5" class="mobImg" src="images/mobs/pathraid3.gif">Rank 3 Rival</div>
    <div class="mobImgDiv"><img id="rival4" alt="5" class="mobImg" src="images/mobs/pathraid4.jpg">Rank 4 Rival</div>
    <div class="mobImgDiv"><img id="rival5" alt="5" class="mobImg" src="images/mobs/pathraid5.jpg">Rank 5 Rival</div>
    <div class="mobImgDiv"><img id="rival6" alt="5" class="mobImg" src="images/mobs/pathraid6.gif">Rank 6 Rival</div>
    <div class="mobImgDiv"><img id="rival7" alt="5" class="mobImg" src="images/mobs/pathraid7.jpg">Rank 7 Rival</div>
    <div class="mobImgDiv"><img id="rival8" alt="5" class="mobImg" src="images/mobs/pathraid8.jpg">Rank 8 Rival</div>
    <div class="mobImgDiv"><img id="rival9" alt="5" class="mobImg" src="images/mobs/pathraid9.gif">Rank 9 Rival</div>
    <div class="mobImgDiv"><img id="rival10" alt="5" class="mobImg" src="images/mobs/pathraid10.gif">Rank 10 Rival</div>
    </div>
    <div id="bottomDiv">Select a mob to raid</div>
    `

    const mobs = document.querySelectorAll('.mobImg');
    for (var i = 0; i < mobs.length; i++){
        mobs[i].addEventListener('click', async function(){

            const profile = await superfetch(`profile?id=${charId}`);
            const crew = (profile.match(/<a href="\/crew_profile\?id=[0-9]+">(.*?)<\/a>/i) || ['',''])[1];

            const myaccount = await superfetch('myaccount');
            const regex = new RegExp(`<td><a target="_top" href="[^"]*">[A-Za-z0-9]+<\\/a><\\/td><td>[0-9]+<\\/td><td>${crew}<\\/td>`,'g')
            const chars = myaccount.replace(/[\n\r]/g,'').replace(/ style="text-align: center;"/g,'').replace(/ <a href="[^"]*"><img border="0" height="13" src="[^"]*" alt="[A-Za-z]+"><\/a>/g,'').match(regex).map(m => `<${m.match(/suid=[0-9]+&serverid=[0-9]+">.*?<\/a>/)}`);
            const rows = [];
            for (var c = 0; c < chars.length; c++){
                const id = chars[c].match(/suid=([0-9]+)/i)[1];
                const name = chars[c].replace(/<.*?>/g,'');
                const check = `<input type="checkbox" class="checkbox" name="${name}" id="${id}">`;
                rows.push(`<tr><td>${check}</td><td>${name}</td></tr>`);
            };
            document.querySelector("#topDiv").style.height = "140px"
            const mobImg = this.outerHTML.match(/src="([^"]*)"/i)[1];
            const mobName = this.outerHTML.match(/id="([^"]*)"/i)[1];
            const minJoiners = this.outerHTML.match(/alt="([^"]*)"/i)[1];
            document.querySelector("#bottomDiv").innerHTML = `
            <div class="dataDivs">
            <img src="${mobImg}" alt="${mobName}" id="selectedRaidMob" style="box-shadow: 5px 5px 5px rgba(0, 0, 0, 1);border-radius:50px"><p style="margin-top:1rem;">
            <hr>
            Characters required: <span id="minCount">${minJoiners}</span><br>
            Characters selected: <span id="charCount">0</span><hr>
            <button class="btn-mm" id="raidMob">RAID MOB</button>
            <button class="btn-mm" id="saveGroup">SAVE GROUP</button>
            </div>
            <div class="dataDivs">
            <h6>SELECTED CHARACTERS</h6>
            <span id="nameList" style="overflow-wrap:break-word"></span>
            </div>
            <div class="dataDivs">
            <h6>AVAILABLE CHARACTERS</h6>
            <table class="table"><tbody>${rows.join('')}</tbody></table>
            </div>
            <div class="dataDivs">
            <h6>SAVED GROUPS</h6>
            <span id="groupList"></span>
            </div>
            `

            await loadSavedGroups();

            async function loadSavedGroups(){

                const groups = [];
                let count = 0

                for (let i = 0; i < 10000000; i++) {
                    const value = GM_getValue(`mobRaiderGroup(${i})`);
                    if (value){
                        count++

                        const groupname = value.split(',').slice(0, 1);
                        const groupchars = value.split(',').slice(1);

                        const html = `
                            <tr id="groupRow${i}">
                            <td><a href="javascript:void(0);" id="group${i}" alt="${groupchars}" class="select-group">${groupname}</a></td>
                            <td><a href="javascript:void(0);" id="group${i}" class="delete-group">[del]</a></td>
                            </tr>`
                            groups.push(html);
                    } else {

                        break;
                    };
                };

                document.querySelector("#groupList").innerHTML = `<table class="table"><tbody>${groups.join('')}</tbody></table>`

                const sel = document.querySelectorAll('.select-group')
                const del = document.querySelectorAll('.delete-group')
                for (let i = 0; i < sel.length; i++) {

                    sel[i].addEventListener('click', async function(){

                        document.querySelectorAll('.checkbox').forEach(checkbox => checkbox.checked = false);

                        const charIds = (this.outerHTML.match(/alt="([^"]*)"/i)[1]).split(',');
                        charIds.forEach(async id => {
                            var checkbox = document.getElementById(id);
                            if (checkbox) checkbox.checked = true;
                            await updateSelectedChars();
                        });
                    });

                    del[i].addEventListener('click', async function(){
                        const num = this.outerHTML.match(/id="group([0-9]+)"/i)[1]
                        GM_deleteValue(`mobRaiderGroup(${num})`);
                        document.querySelector(`#groupRow${num}`).remove();
                    });
                };
            };

            const boxes = document.querySelectorAll('.checkbox')
            for (let i = 0; i < boxes.length; i++) {
                boxes[i].addEventListener('click', async function(){
                    await updateSelectedChars();
                });
            };

            async function updateSelectedChars(){
                const allChecked = document.querySelectorAll('.checkbox:checked')
                document.querySelector("#charCount").innerHTML = allChecked.length;
                const nameList = (Array.from(allChecked).map(node => node.outerHTML.match(/name="([^"]*)"/i)[1])).join(',');
                document.querySelector("#nameList").innerHTML = nameList;
            };

            document.querySelector("#saveGroup").addEventListener('click', async function(){

                if (document.querySelector("#charCount").innerHTML == "0"){
                    alert('Please select characters before trying to save a group');
                    return;
                };

                var name = prompt("Enter a name for the group");

                if (name == ''){
                    alert ('You did not enter a name. The group was not saved');

                } else {
                    const allChecked = document.querySelectorAll('.checkbox:checked');
                    const idList = (Array.from(allChecked).map(node => node.outerHTML.match(/id="([0-9]+)"/i)[1])).join(',');
                    const listName = name.replace(/ /g,'').replace(/,/g,'');
                    for (let i = 0; i < 10000000; i++) {
                        const value = GM_getValue(`mobRaiderGroup(${i})`);
                        if (!value){
                            GM_setValue(`mobRaiderGroup(${(i)})`, listName + ',' + idList);
                            await loadSavedGroups();
                            break;
                        };
                    };
                };
            });

            document.querySelector("#raidMob").addEventListener('click', async function(){
                const reqChars = document.querySelector("#minCount").innerHTML
                const selChars = document.querySelector("#charCount").innerHTML
                if (reqChars <= selChars){
                    const allChecked = document.querySelectorAll('.checkbox:checked');
                    const idList = (Array.from(allChecked).map(node => node.outerHTML.match(/id="([^"]*)"/i)[1])).join(',');
                    const raidMob = document.querySelector("#selectedRaidMob").alt;
                    await mmplus(`RaidMob|rganame|${server}|${raidMob}|${idList}`);
                } else {
                    alert(`Please select ${reqChars} characters to raid this mob with`);
                };
            });
        });
    };
};


async function casterMenuOpen() {
    travelMenuClose();
    appsMenuClose();
    searchMenuClose();

    document.querySelector("#btnCaster > img").classList.toggle('rotate180');
    GM_addStyle (`#btnCaster > img {transition: transform 0.5s ease;}`);
    GM_addStyle (`.rotate180 {transform: rotate(180deg);}`);

    document.querySelector("#btnCaster").removeEventListener("click",casterMenuOpen);
    setTimeout(function() {document.querySelector("#btnCaster").addEventListener("click", casterMenuClose);},1000);

    if (casterMenuCreated == false){
        const profile = await superfetch('profile');

        let potsArray = [];
        const potionBp = await fetch('ajax/backpackcontents.php?tab=potion').then(res => res.text());
        const allPots = potionBp.match(/data-iid="[0-9]+" id="[^"]*" class="[^"]*" src="[^"]*"/g);
        for (let i = 0; i < allPots.length; i++) {
            const potion = allPots[i]
            const potId = potion.match(/data-iid="([0-9]+)"/i)[1]
            const potImg = potion.match(/src="([^"]*)"/i)[1]
            if (!profile.replace(/skills\/\.\.\//g,'').match(potImg)){
                potsArray.push(`<img src="${potImg}" class="castable cast-potion" id="${potId}" onmouseover="itempopup(event,'${potId}')" onmouseout="kill()">`);
            };
        };

        let skillsArray = [];
        let skillIdArray = [];
        const classEndpoints = ['cast_skills.php','cast_skills.php?C=4','cast_skills.php?C=5','cast_skills.php?C=6','cast_skills.php?C=7']
        const skillClasses = await Promise.all(classEndpoints.map(endpoint => fetch(endpoint).then(res => res.text())));
        for (let i = 0; i < skillClasses.length; i++) {
            const skillIds = skillClasses[i].match(/loadskill\([0-9]+\)/g) || [];
            for (let i = 0; i < skillIds.length; i++) {
                skillIdArray.push(skillIds[i].match(/[0-9]+/i))
            };
        };
        const skillInfos = await Promise.all(skillIdArray.map(endpoint => fetch(`skills_info.php?id=${endpoint}`).then(res => res.text())));
        for (let i = 0; i < skillInfos.length; i++) {
            const info = skillInfos[i]
            if (info.match(`<input type="submit" name="cast" class="btn btn-primary" value="Cast Skill">`)){
                const skillName = info.match(/<h5>(.*?)<\/h5>/i)[1]
                const skillImg = info.match(/style="[^"]*" src="([^"]*)"/i)[1]
                const skillId = info.match(/value="([0-9]+)"/i)[1]
                const skillText = info.replace(/'/g,'').match(/<h5>.*[\n\r](.*)<\/div>/)[1]
                if (!profile.match(skillImg)){
                    skillsArray.push(`<img src="${skillImg}" class="castable cast-skill" id="${skillId}" onmouseover="statspopup(event,'<b>${skillName}</b><br>${skillText}')" onmouseout="kill()">`)
                };
            };
        };

        const casterHtml = `
        <center>
        <h4>Skills</h4>
        <div id="casterSkills">${skillsArray.join(' ')}</div><hr>
        <h4>Potions</h4>
        <div id="casterPotions">${potsArray.join(' ')}</div><hr>
        <button class="btn-mm" id="casterSelectAll">Select All Skills</button>
        <button class="btn-mm" id="casterDeselectAll">Deselect All Skills</button>
        <button class="btn-mm" id="casterCastAll">Cast Selected</button>
        `

        var image = document.querySelector("#btnCaster").getBoundingClientRect();
        var newDiv = document.createElement('div');
        newDiv.id = 'casterDiv';
        newDiv.classList.toggle('widget');
        newDiv.innerHTML = casterHtml;
        newDiv.style.position = 'absolute';
        newDiv.style.top = image.top + window.scrollY + 'px';
        newDiv.style.left = image.left + window.scrollX-650 + 'px';
        document.body.appendChild(newDiv);


        $(function () {
            $('#casterDiv').on('click','img',(function() {
                $(this).toggleClass("caster-selected");
            }));
        });
    };

    let serverNo;
    let server;
    if (window.location.toString().match('sigil')){
        serverNo = 1
        server = 'sigil'
    };
    if (window.location.toString().match('torax')){
        serverNo = 2
        server = 'torax'
    };
    const charId = document.body.innerHTML.match(/outwar\.com\/page\?x=([0-9]+)/i)[1]

    document.querySelector("#casterSelectAll").addEventListener('click', function() {
        $("#casterSkills > img").addClass("caster-selected");
    });
    document.querySelector("#casterDeselectAll").addEventListener('click', function() {
        $("#casterSkills > img").removeClass("caster-selected");
    });
    document.querySelector("#casterCastAll").addEventListener('click', async function() {

        const selectedImages = document.querySelector("#casterDiv").querySelectorAll("img.caster-selected");
        const imgIds = Array.from(selectedImages).map(img => img.id);
        await mmplus(`Cast|rganame|${server}|${charId}|${imgIds.join(',')}`);
        await casterMenuClose();
    });

    GM_addStyle (`#casterDiv {animation: moveAnimation 0.5s ease forwards;position:fixed;}`)
    GM_addStyle (`@keyframes moveAnimation {0% {width:700px;height:0px;position:fixed;top:0px;} 100% {width:700px;height:535px;position:fixed;top:45px;}}`)
    casterMenuCreated = true;
};


async function searchMenuOpen() {
    travelMenuClose();
    appsMenuClose();
    casterMenuClose();

    document.querySelector("#btnSearch > img").classList.toggle('rotate180');
    GM_addStyle (`#btnSearch > img {transition: transform 0.5s ease;}`);
    GM_addStyle (`.rotate180 {transform: rotate(180deg);}`);

    document.querySelector("#btnSearch").removeEventListener("click", searchMenuOpen);
    document.querySelector("#btnSearch").addEventListener("click", searchMenuClose);
    if (searchMenuCreated == false){

        const searchHtml = `
        <h4>Search</h4>
        <form method="post" action="playersearch.php" target="_parent" style="display:inline-block;">
        <input style="width:230px;" id="t-text" name="search" type="text" placeholder="PLAYER" class="form-control-new mb-2" autocomplete="off">
        </form>
        <br>
        <form method="post" action="crewsearch.php" target="_parent" style="display:inline-block">
        <input style="width:230px;" id="t-text" name="search" type="text" placeholder="CREW" class="form-control-new mb-2" autocomplete="off">
        </form>
        <br>
        <input style="width:230px;" id="treasurySearch" type="text" placeholder="TREASURY" class="form-control-new mb-2" autocomplete="off">
        <br>
        <input style="width:230px;" id="rgaSearch" type="text" placeholder="ITEM ON RGA" class="form-control-new mb-2" autocomplete="off">
        <br>
        <div id="rgaSearchDiv"></div>
        `

        var image = document.querySelector("#btnSearch").getBoundingClientRect();
        var newDiv = document.createElement('div');
        newDiv.id = 'searchDiv';
        newDiv.classList.toggle('widget');
        newDiv.innerHTML = searchHtml;
        newDiv.style.position = 'absolute';
        newDiv.style.top = image.top + window.scrollY + 'px';
        newDiv.style.left = image.left + window.scrollX-220 + 'px';
        document.body.appendChild(newDiv);

        document.querySelector("#treasurySearch").addEventListener("keyup", function(event) {

            if (event.keyCode === 13) {
                const treasuryLookupItem = document.querySelector("#treasurySearch").value.replace(/ /g,'+')
                window.location.href = `treasury?search_for=${treasuryLookupItem}`
            };
        });

        document.querySelector("#rgaSearch").addEventListener("keyup", async function(event) {

            if (event.keyCode === 13) {

                document.body.style.pointerEvents = 'none';
                document.querySelector("#container").setAttribute('style','opacity:0.25; transition: opacity 0.5s ease;');
                document.querySelector("body > center > div.sub-header-container").setAttribute('style','opacity:0.25; transition: opacity 0.5s ease;');

                const startingCharId = document.body.innerHTML.match(/<option value="([0-9]+)" selected/i)[1]

                GM_addStyle (`#searchDiv {animation: growSearch 0.5s ease forwards;position:fixed;}`)
                GM_addStyle (`@keyframes growSearch {0% {width:270px;height:275px;position:fixed;top:45px;} 100% {width:270px;height:500px;position:fixed;top:45px;}}`)

                const itemName = document.querySelector("#rgaSearch").value.toUpperCase()
                document.querySelector("#rgaSearchDiv").innerHTML = `
                <div id="rgaSearchResults" style="max-height:280px;overflow:auto;">
                <img src="https://studiomoxxi.com/moxximod/loading-gif.gif" style="height:75px;width:75px;padding:10px">
                </div>
                `;

                const charDropdown = document.body.innerHTML.replace(/[\n\r]/g,'').match(/<optgroup label="My Characters">.*?<option value="0">--Change Server--<\/option>/i)
                const charIdArray = charDropdown.toString().match(/value="[0-9]+"/g).map(match => match.match(/[0-9]+/)[0]).slice(0, -1);
                let rows = []
                const lookForItem = async (id) => {
                    let found = 0;

                    const matchBp = new RegExp(`data-itemidqty="[0-9]+" data-name="${itemName}"`, 'i');
                    const types = ['regular', 'quest', 'orb', 'potion', 'key'];
                    for (const type of types) {
                        const look = await superfetch(`ajax/backpackcontents.php?tab=${type}&suid=${id}`);
                        found += look.match(matchBp) ? parseInt(look.match(matchBp).toString().match(/data-itemidqty="([0-9]+)"/i)[1]) : 0
                    };

                    const matchEq = new RegExp(`alt="${itemName}"`, 'i');
                    const lookEq = await superfetch(`equipment?suid=${id}`);
                    found += lookEq.match(matchEq) ? 1 : 0

                    if (found > 0){
                        const profile = await superfetch(`profile?suid=${id}`);
                        const name = `<a href='home.php?suid=${id}'>${profile.match(/<font size="3">(.*?)<\/font>/i)[1]}</a>`;
                        rows.push(`<tr><td>${name}</td><td>${found}</td></tr>`);
                    };
                };
                await Promise.all(charIdArray.map(lookForItem));

                await superfetch(`ajax_changeroomb.php?suid=${startingCharId}`);

                document.querySelector("#rgaSearchResults").innerHTML = `
                <table class="table table-striped sortable" style="text-align:left;border-radius:10px;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);">
                <thead><tr><th>Char</th><th>Qnt</th></tr></thead>
                <tbody>
                ${rows.join('')}
                </tbody>
                </table>
                `

                await sortableTables();

                document.body.style.pointerEvents = 'auto';
                document.querySelector("#container").setAttribute('style','opacity:1; transition: opacity 0.5s ease;');
                document.querySelector("body > center > div.sub-header-container").setAttribute('style','opacity:1; transition: opacity 0.5s ease;');
            };
        });
    };

    GM_addStyle (`#searchDiv {animation: moveAnimation 0.5s ease forwards;position:fixed;}`)
    GM_addStyle (`@keyframes moveAnimation {0% {width:270px;height:0px;position:fixed;top:0px;} 100% {width:270px;height:275px;position:fixed;top:45px;}}`)
    searchMenuCreated = true;
};


async function searchMenuClose(){
    document.querySelector("#btnSearch > img").classList.remove('rotate180');
    document.querySelector("#btnSearch").addEventListener("click", searchMenuOpen);
    GM_addStyle (`#searchDiv {animation: rewindSearch 0.5s ease forwards;}`)
    GM_addStyle (`@keyframes rewindSearch {0% {width:270px;height:275px;position:fixed;top:45px;} 100% {width:270px;height:0px;position:fixed;top:-1000px;}}`)

    if (document.querySelector("#rgaSearchDiv")){
        document.querySelector("#rgaSearchDiv").innerHTML = '';
    }
}


async function travelMenuClose(){
    document.querySelector("#btnTravel > img").classList.remove('rotate180');
    document.querySelector("#btnTravel").addEventListener("click", travelMenuOpen);
    GM_addStyle (`#travelDiv {animation: rewindTravel 0.5s ease forwards;}`)
    GM_addStyle (`@keyframes rewindTravel {0% {width:370px;height:535px;position:fixed;top:45px;} 100% {width:370px;height:0px;position:fixed;top:-1000px;}}`)
}


async function appsMenuClose(){
    document.querySelector("#btnApps > img").classList.remove('rotate180');
    document.querySelector("#btnApps").addEventListener("click", appsMenuOpen);
    GM_addStyle (`#appsDiv {animation: rewindApps 0.5s ease forwards;}`)
    GM_addStyle (`@keyframes rewindApps {0% {width:435px;height:535px;position:fixed;top:45px;} 100% {width:435px;height:0px;position:fixed;top:-1000px;}}`)

}


async function casterMenuClose(){
    document.querySelector("#btnCaster > img").classList.remove('rotate180');
    document.querySelector("#btnCaster").addEventListener("click", casterMenuOpen);
    GM_addStyle (`#casterDiv {animation: rewindCaster 0.5s ease forwards;}`)
    GM_addStyle (`@keyframes rewindCaster {0% {width:700px;height:535px;position:fixed;top:45px;} 100% {width:700px;height:0px;position:fixed;top:-1000px;}}`)
}


async function skillsTab(profile){

    if (document.URL.match(/\bhome\b/) || document.URL.match(/\bprofile$\b/) || document.URL.match('world')) {
        return;
    };
    const booster = profile.match(/left:258px; top:346px; width:32px; height:32px;text-align:center">[\n\r]<img style="border:0px;" src="[^"]*" onclick="window\.location='[^']*'" ONMOUSEOVER="itempopup\(event,'[0-9]+'\)" ONMOUSEOUT="kill\(\)" alt="[^"]*">/i);
    const allCast = profile.match(/<img align="absmiddle" border="0" src="[^"]*" hspace="2" width="25" height="25" alt=".*?" ONMOUSEOVER="popup\(event,'.*?',[0-9]+\)" ONMOUSEOUT="kill\(\)">/g)
    if (allCast || booster){
        const allCastString = allCast.map((element, index) => index % 2 === 0 ? element : element + '<br>').join(' ');
        const firstExpire = allCast.reduce((min, currentItem) => Math.min(min, (currentItem.match(/\d+\s*hour|\d+\s*min/g) || []).map(match => parseInt(match) * (match.includes('hour') ? 60 : 1)).reduce((acc, val) => acc + val, 0)), Infinity);
        var newDiv = document.createElement('div');
        newDiv.id = 'skillsTab';
        newDiv.classList.toggle('widget');
        newDiv.innerHTML = `<div id="tabBooster"></div><div id="tabSpacer"></div><div id="tabSkills"></div><sub id="closeSkillsTab" style="position:absolute;right:0px;top:10px;">x</sub>`
        document.body.appendChild(newDiv);
        document.querySelector("#closeSkillsTab").addEventListener('click', async function(){
            document.querySelector("#skillsTab").remove();
        });
        if (allCast){
            document.querySelector("#tabSkills").innerHTML = `${firstExpire} MINS<br>${allCastString}`
        }
        if (booster){
            const boosterImg = booster.toString().match(/src="([^"]*)"/i)[1];
            const boosterId = booster.toString().match(/event,'([0-9]+)'/i)[1];
            const boosterFetch = await superfetch(`item_rollover.php?id=${boosterId}`);
            const boosterMin = parseInt(boosterFetch.match(/([0-9]+) minutes/i)[1])
            const calculate = minutesToAdd => new Date(new Date().setMinutes(new Date().getMinutes() + minutesToAdd)).toLocaleString('en-US', {month:'2-digit', day:'2-digit', year:'2-digit', hour:'2-digit', minute:'2-digit', hour12: false}).replace(',', '<br>');
            const expires = calculate(boosterMin);
            document.querySelector("#tabBooster").innerHTML = `${expires}<br><img src="${boosterImg}" onmouseover="itempopup(event,'${boosterId}')" onmouseout="kill()">`
        };
        if (booster && allCast){
            document.querySelector("#tabSpacer").innerHTML = "<hr>"
        };
    };
};


async function bossSpawns(){

    const size = 280
    GM_addStyle (`
    #bossSpawnDiv{width:1030px;text-align:left;}
    div.bossSpawnTile{display:inline-block;height:${size}px;overflow:hidden;box-shadow: 0 0 10px rgba(0, 0, 0, 1);margin:4px;text-align:center;border-radius:4px;}
    div.bossSpawnTile > img{width:${size}px;height:${size}px;}
    div.bossSpawnText{width:${size-30}px;position:relative;left:15px;top:-200px;background:#000000;padding:15px;border-radius:15px;font-size:14px;opacity:0.9;box-shadow: 0 0 3px rgba(0, 0, 0, 1);}
    `);

    var bosses = document.querySelectorAll(".col-12.col-xl-6");
    const bossesArray = [];
    bosses.forEach(function(div) {
        const i = div.innerHTML
        const img = i.match(/img src="([^"]*)"/i)[1]
        const name = i.match(/<b>(.*?)<\/b>/i)[1].replace(/(,.*| .*)/g, '')
        const spawnid = i.match(/boss_stats\.php\?spawnid=([0-9]+)/i)[1]
        const form = i.match(/formraid\.php\?target=[0-9]+/i) ? `<a href="${i.match(/formraid\.php\?target=[0-9]+/i)}">Form Raid</a>` : ''
        const health = i.match(/<p class="card-user_occupation"> [0-9]+%/i) ? `<hr><h5>${i.match(/<p class="card-user_occupation"> ([0-9]+)%/i)[1]}%</h5>` : ''
        bossesArray.push(`
            <div class="bossSpawnTile">
            <img src="${img}"><br>
            <div class="bossSpawnText">
            <h5><b>${name.toUpperCase()}</b></h5>
            <a href="boss_stats.php?spawnid=${spawnid}">Crew Table</a>
            ${health}
            ${form}
            </div>
            </div>
            `);
    });
    document.querySelector("#content").innerHTML = `
    ${bossesArray.join('')}
    `;
};

async function bossStats(){

    GM_addStyle(`
    img.bossCrewPic{width:30px;height:30px;}
    div.bossStatsContainer{position:relative;width: 50%;flex-grow: 8;margin-top: 130px;margin-bottom: 0;margin-left: 212px;max-width: 1300px;}
    @keyframes fadeIn {from {opacity: 0;} to {opacity: 1;}}
    #content{display:none !important;}
    #bossTableDiv{animation: bossTable 2s ease forwards;}
    @keyframes bossTable {0% {opacity:0;} 100% {opacity:1}}");
    `)

    const boss = document.body.innerHTML.match(/<h1 class="w-100">(.*?)<\/h1>/i)[1];
    const specs = await info(boss);

    const newDiv = document.createElement("div");
    newDiv.classList.add('bossStatsContainer')
    newDiv.innerHTML = `
    <div class="widget mb-3">
    <h1>${boss}
    <a onmouseover="popup(event,'${specs[2]}')" onmouseout="kill()"><img src="https://studiomoxxi.com/moxximod/loot.png" height="20px" style="margin-bottom:10px"></a>
    </h1>
    <span id="hpremaining"></span>
    </div>
    <img src="https://studiomoxxi.com/moxximod/loading-gif.gif" width="80px" height="80px" id="loading">
    <div id="bossTableContainer">
    </div>
    `
    document.querySelector("#container").appendChild(newDiv);

    const rows = document.querySelectorAll("#content-header-row > div > table > tbody > tr");
    let totItems = 0;
    let obj = []
    rows.forEach(function(i) {
        const crew = i.innerHTML.match(/<font color="#CC0000">(.*?)<\/font>/i)[1];
        const id = i.innerHTML.match(/crew_profile\.php\?id=([0-9]+)/i)[1];
        const dmg = i.innerHTML.replace(/,|\(.*?\)| /g, '').match(/<td>([0-9]+)<\/td>/i)[1];
        const items = i.innerHTML.replace(/'/g,'').match(/<td onmouseover="popup\(event,([^']*),808080\)" onmouseout="kill\(\)">([0-9]+)<\/td>/i);

        obj.push({crew: crew, id: id, dmg: dmg, loot: items[1], count: items[2]})

        totItems += parseInt(items[2]);
    });
    if (totItems > 0){
        await bossStatus_dead(obj);
    } else {
        await bossStatus_alive(boss,obj,specs);
    };
};

async function bossStatus_alive(boss,obj,specs){
    const data = [];

    const total = obj.reduce((acc, obj) => acc + parseInt(obj.dmg), 0);
    const hp = specs[0];
    const totloot = specs[1];
    document.querySelector("#hpremaining").innerHTML = `<h5>Health Remaining: ${(hp-total).toLocaleString()} (${((hp-total)/hp*100).toFixed(3)}%)</h5>`
    let active = 0;
    let dmgpmin = 0;
    const getData = async (c) => {

        const crew = c.crew;

        const id = c.id;

        const dmg = parseInt(c.dmg);

        const perc = (dmg/total*100).toFixed(3);

        const fetch = await superfetch(`crew_raidresults.php?crewid=${id}`);
        const regex = new RegExp(`<td align="left" valign="top">([0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+[A-Za-z]m)<\/td><td align="left" valign="top">${boss}<\\/td><td align="left" valign="top">[0-9]+<\\/td><td align="left" valign="top"> <font color="[^"]*"><b>[A-Za-z]+<\/b><\\/font><\\/td><td align="left" valign="top"><a href="raidattack\\.php\\?raidid=([0-9]+)">View<\\/a><\\/td>`,'i')

        const last = fetch.replace(/[\n\r]/g,'').match(regex);
        const raidtime = last ? fetch.replace(/[\n\r]/g,'').match(regex)[1].replaceAll("-","/").replace("am",":00 AM").replace("pm",":00 PM").replace(/ 0/i," ") : '01/01/01 01:01:01 AM';
        var d = new Date();
        var utc = d.getTime() + (d.getTimezoneOffset() * 60000);
        var owtime = new Date(utc + (3600000 * parseFloat('-5.0')));
        const sinceLast = (owtime - new Date(raidtime))/3600000

        const raid = fetch.replace(/[\n\r]/g,'').match(regex);
        const raidid = raid ? fetch.replace(/[\n\r]/g,'').match(regex)[2] : '0';
        const raidattack = await superfetch(`raidattack.php?raidid=${raidid}`);
        const parse = new DOMParser().parseFromString(raidattack, 'text/html');

        const raiddmg = raidattack.replace(/,/g,'').match(/<i>Total Attacker Damage: [0-9]+<\/i>/i) ? parseInt(raidattack.replace(/,/g,'').match(/<i>Total Attacker Damage: ([0-9]+)<\/i>/i)[1]).toLocaleString() : '--';
        let status;
        if (sinceLast <= 0.033){
            status = '<b><font color="#00ff00">ACTIVE</font></b>';
            dmgpmin += parseInt(raiddmg.replace(/,/g,''));
            active += 1;
        } else if (sinceLast < 1){
            status = '<b><font color="#00ff00">ACTIVE</font></b>';
            active += 1;
        } else {
            status = `<a style="opacity:0.5">INACTIVE</a>`;
        };

        const char = (parse.querySelector("#message_0 > div > div > span > b") || {textContent: "na"}).textContent.replace(/ .*/i,"")
        const profile = await superfetch(`profile?transnick=${char}`);
        const markdown = profile.match(/<b>Level [0-9]+ Markdown<\/b>/i) ? profile.match(/<b>Level [0-9]+ Markdown<\/b><br \/>You become more focused and alert for battle\. Decreases cost by [0-9]+% to form\/join raids\.<br \/>(.*?) left<br>/i)[1] : "--"

        const crewPro = await superfetch(`crew_profile?id=${id}`);
        const pic = crewPro.match(/https:\/\/upload\.outwar\.com\/crewuploaded\/[A-Za-z][0-9]+\.[A-Za-z]+/i) || "images/logodefault.gif";

        data.push({
            pic: `<img src="${pic}" class="bossCrewPic">`,
            name: `<a href="crew_profile?id=${id}">${crew}</a>`,
            dmg: dmg,
            perc: `${perc}%`,
            items: Math.floor(parseInt(dmg)/hp*totloot),
            projected: Math.floor(perc/100*totloot),
            status: status,
            raid: raiddmg,
            md: markdown
        });
    };
    await Promise.all(obj.map(getData));

    data.sort((a, b) => b.dmg - a.dmg);

    const rows = data.map(({ pic, name, dmg, perc, items, projected, status, raid, md }) => `
    <tr>
    <td>${pic}</td>
    <td>${name}</td>
    <td>${dmg.toLocaleString()}</td>
    <td>${perc}</td>
    <td>${items}</td>
    <td>${projected}</td>
    <td>${status}</td>
    <td>${raid}</td>
    <td>${md}</td>
    </tr>
    `);

    document.querySelector("#loading").remove();

    document.querySelector("#bossTableContainer").innerHTML = `
    <div id="bossTableDiv" class="widget">
    <div class="list-group-item">
    <i>There are ${active} crews actively raiding doing ${dmgpmin.toLocaleString()} damage per minute</i>
    </div>
    <table class="table table-striped">
    <thead><tr><th></th><th>Crew</th><th>Damage</th><th>Percent</th><th>Items</th><th>Projected</th><th>Status</th><th>Last Raid</th><th>Markdown</th></tr></thead>
    <tbody>
    ${rows.join('')}
    </tbody>
    </table>
    </div>
    `
};

async function bossStatus_dead(obj){
    const highlight = {
        value: ['Blazing Serpent','Ghostly Stalker','Exalted Perfection','Transcended Extract','Blossom','Experience Ward'],
        rare: ['Augment of Simulation','Catalyst','Augment of Madness','Tier 2 Booster Upgrade','Reborn Knight','8-Bit Banana'],
        epic: ['Descendant','Ancestral','Boon of Vision']
    };
    const data = [];

    const getData = async (c) => {

        const crew = c.crew;

        const id = c.id;

        const dmg = parseInt(c.dmg);

        const count = c.count;

        const loot = c.loot.split('<br>');

        const lootStyled = loot.map(value =>
            highlight.value.some(item => value.includes(item))
            ? `<font color="#FFDE5B">${value}</font>`
            : highlight.rare.some(item => value.includes(item))
            ? `<font color="#FF8000">${value}</font>`
            : highlight.epic.some(item => value.includes(item))
            ? `<font color="#FF00FF">${value}</font>`
            : value
        );

        const crewPro = await superfetch(`crew_profile?id=${id}`);
        const pic = crewPro.match(/https:\/\/upload\.outwar\.com\/crewuploaded\/[A-Za-z][0-9]+\.[A-Za-z]+/i) || "images/logodefault.gif";
        data.push({crew:crew,pic:pic,id:id,dmg:dmg,count:count,loot:lootStyled.slice(0, -1).join(', ')});
    };
    await Promise.all(obj.map(getData));

    data.sort((a, b) => b.dmg - a.dmg);

    const rows = data.map(({ crew, pic, dmg, count, loot}) => `
    <tr>
    <td><img src="${pic}" class="bossCrewPic"></td>
    <td>${crew}</td>
    <td>${dmg.toLocaleString()}</td>
    <td>${count}</td>
    <td>${loot}</td>
    </tr>
    `);

    document.querySelector("#loading").remove();

    document.querySelector("#bossTableContainer").innerHTML = `
    <div id="bossTableDiv" class="widget">
    <table class="table table-striped">
    <thead><tr><th></th><th>Crew</th><th>Damage</th><th>Items</th><th>Loot</th></tr></thead>
    <tbody>
    ${rows.join('')}
    </tbody>
    </table>
    </div>
    `
};


async function itemTransfer(){

    GM_addStyle(`
    #items > img, #itemsSelectedDiv > img {position:revert;height:40px;width:40px;margin:5px;border-radius:5px;transform:translate(0%,0%);background-color:#000000;}
    .item-desel {border:2px #475254 SOLID !important;}
    .item-sel {border:3px #00CC00 SOLID !important;padding:2px;animation: item-selected 1s infinite;}
    #itemsSelectedDiv > img{cursor: pointer;}
    @keyframes item-selected{0% {filter: saturate(100%);} 50% {filter: saturate(250%); } 100% {filter: saturate(100%);}}
    `)

    const charDropdown = document.querySelector("#divHeader > select")
    charDropdown.classList.add('form-control-new')
    charDropdown.setAttribute('style','font-size:15px;padding:0.75rem;border-radius:6px;margin-bottom:0.5rem;width:100%;');

    const allItems = (document.querySelector("#divItemtransfer").innerHTML.match(/<img alt="[^"]*" style="[^"]*" src="[^"]*" onmouseover="itempopup\(event,[0-9]+, [0-9]+, '', [0-9]+\)" onmouseout="kill\(\)">/g) ?? []).map(i => (i.replace('src','class="item item-desel" src')));

    document.querySelector("#content").innerHTML = `
        <div class="row justify-content-center" id="content-header-row">
        <div class="bio col-lg-8 col-md-8 col-sm-12 col-12 layout-spacing layout-spacing">
        <div style="display:inline-block;text-align:left; width: 100%;" id="items">
        <h4>Item Transfer</h4><hr style="margin-top:10px;margin-bottom:10px;">
        ${allItems.join('')}
        </div></div>
        <div class="col-lg-4 col-md-4 col-sm-12 col-12 layout-spacing layout-spacing" style="text-align:left">
        <div class="widget text-left mb-3">
        <h6>Items Selected: <span id="selectedCount">0</span></h6>
        <div id="itemsSelectedDiv"></div>
        </div>
        <div class="widget text-left mb-3">
        <h4>Send Items</h4>
        ${charDropdown.outerHTML}<br>
        <button id="sendItems" class="btn-mm">SEND ITEMS</button><button id="setDefaultChar" class="btn-mm">SET DEFAULT CHAR</button>
        <hr>
        <span id="togglePb"></span>
        </div></div></div>
        `

    if (window.location.href.match('Playerbound=1')){
        document.querySelector("#togglePb").innerHTML = `<a href="itemtransfer.php?includePlayerbound=0">Hide playerbound items</a>`
    } else {
        document.querySelector("#togglePb").innerHTML = `<a href="itemtransfer.php?includePlayerbound=1">Show playerbound items</a>`
    };

    if (GM_getValue("transferDefault")){
        const charId = GM_getValue("transferDefault")
        document.querySelector('select[name="self"]').value = charId;
    };

    const items = document.querySelectorAll(".item")
    const itemHandling = async (item) => {

        item.addEventListener('click', async function(){
            item.classList.toggle('item-sel')
            item.classList.toggle('item-desel')
            await updateItemsSelected();
        });

        item.addEventListener('dblclick', async function(){
            const itemName = item.outerHTML.match(/alt="([^"]*)"/i)[1]
            const all = document.querySelectorAll(`img[alt="${itemName}"]`);
            const selectAll = async (item) => {
                item.classList.toggle('item-sel')
                item.classList.toggle('item-desel')
            }
            await Promise.all(Array.from(all).map(selectAll));
            await updateItemsSelected();
        });
    };
    await Promise.all(Array.from(items).map(itemHandling));

    async function updateItemsSelected(){
        document.querySelector("#itemsSelectedDiv").innerHTML = ''
        const selectedItems = document.querySelectorAll(".item-sel");
        const selectedArray = []
        for (let i = 0; i < selectedItems.length; i++) {
            selectedArray.push(selectedItems[i].outerHTML.replace('item-sel','item-desel'))
        };
        document.querySelector("#itemsSelectedDiv").innerHTML = selectedArray.join('');
        document.querySelector("#selectedCount").innerHTML = selectedArray.length;
    };

    document.querySelector("#sendItems").addEventListener('click', async function(){
        await loadingOverlay()
        const itemIds = document.querySelector("#itemsSelectedDiv").innerHTML.match(/event,[0-9]+/g).map(i => `&checkbox%5B%5D=${i.match(/[0-9]+/)[0]}`).join('');
        const charId = document.querySelector('select[name="self"]').value;
        await superpost('itemtransfer',`self=${charId}&submit=Send+items%21${itemIds}`);

        document.querySelector("#itemsSelectedDiv").innerHTML = '';
        const selectedItems = document.querySelectorAll(".item-sel");
        document.querySelector("#selectedCount").innerHTML = '0'
        for (let i = 0; i < selectedItems.length; i++) {
            selectedItems[i].remove();
        };
        await loadingOff();
    })

    document.querySelector("#setDefaultChar").addEventListener('click', function(){
        const charId = document.querySelector('select[name="self"]').value;
        GM_setValue("transferDefault",charId);
    })
};


async function crewVault(){

    GM_addStyle(`
    .crew_itembox_item{position:revert;height:40px;width:40px;max-width:40px;max-height:40px;margin:5px;border-radius:5px;transform:translate(0%,0%);border:2px #475254 SOLID !important;background-color:#000000;}
    .crew_itembox_item:hover{animation: pulse 1s infinite;cursor: pointer;}
    .item-selected{border:3px #00CC00 SOLID !important;padding:2px;animation: item-selected 1s infinite;}
    #itemsSelectedDiv > img{cursor: pointer;}
    @keyframes item-selected{0% {filter: saturate(100%);} 50% {filter: saturate(250%); } 100% {filter: saturate(100%);}}
    .btn-mm{margin-left:0px;}
    img.cvSelectAllImg{height:40px;width:40px;margin:2px;border-radius:5px;transform:translate(0%,0%);border: 2px #475254 SOLID !important;background-color: #000000;}
    img.cvSelectAllImg:hover{animation: pulse 1s infinite;cursor: pointer;}
    `)

    const manager = document.body.innerHTML.match(/<h5>Award Item<\/h5>/i) ? true : false;

    let cvItems;
    const points = document.body.innerHTML.replace(/,/g,'').match(/event'([0-9]+\.[0-9]+) Crew Points/i)[1]
    const capacity = document.body.innerHTML.match(/Currently Storing <b>([0-9]+) \/ ([0-9]+)<\/b>/i)

    if (manager){
        let nonce = document.body.innerHTML.match(/name="form-nonce" value="([^"]*)"/i)[1]
        const awardTo = document.querySelector('select[name="awardto"]');
        const rbSel = document.querySelector('select[name="rbsel"]');
        cvItems = document.body.innerHTML.replace(/[\n\r]/g,'').match(/<img alt="[^"]*" class="[^"]*" id="[^"]*" src="[^"]*" style="border:0px;" onmouseover="itempopup\(event,'[0-9]+'\)" onmouseout="kill\(\)" ondblclick="selectAllItem\('[0-9]+'\);kill\(\);" onclick="selectItem\('[0-9]+'\);kill\(\);"><input type="checkbox" name="[^"]*" class="[^"]*" id="[^"]*" value="[0-9]+" style="[^"]*">/g)
        document.querySelector("#content").innerHTML = `
        <div class="row justify-content-center" id="content-header-row">
        <div class="bio col-lg-8 col-md-8 col-sm-12 col-12 layout-spacing layout-spacing">
        <div style="display:inline-block;text-align:left; max-width: 100%;" id="cvitems">
        <h4>Crew Vault</h4><hr style="margin-top:10px;margin-bottom:10px;">
        ${cvItems.join('')}<br><br>
        &emsp;<i>*Items listed on crew treasury will not appear in MoxxiMod crew vault</i>
        </div></div>
        <div class="col-lg-4 col-md-4 col-sm-12 col-12 layout-spacing layout-spacing" style="text-align:left">
        <div class="button-container mb-3" style="display:inline-block;"><div class="btn-group show" role="group">
        <button type="button" class="btn-mm dropdown-toggle" data-toggle="dropdown">STORAGE MENU <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg></button>
        <div class="dropdown-menu" style="will-change: transform; position: absolute; transform: translate3d(0px, 38px, 0px); top: 0px; left: 0px;">
        <a class="dropdown-item" href="crew_pointbank">Point Bank</a>
        <a class="dropdown-item" href="crew_treasury">Crew Treasury</a>
        <a class="dropdown-item" href="crew_stones">Upgrade Stones</a>
        <a class="dropdown-item" href="crew_actionlog.php?l=Award%20Item">Award Log</a>
        <a class="dropdown-item" href="crew_actionlog.php?l=Delete%20Item">Deleted Log</a>
        </div></div></div>
        <div class="button-container mb-3" style="display:inline-block;"><div class="btn-group show" role="group">
        <button type="button" class="btn-mm dropdown-toggle" data-toggle="dropdown">QUICK SELECT <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg></button>
        <div class="dropdown-menu" style="will-change: transform; position: absolute; transform: translate3d(0px, 38px, 0px); top: 0px; left: 0px;">
        <img id="saEthl" src="images/items/arheart.jpg" class="cvSelectAllImg" onmouseover="statspopup(event,'Ethereal Quest Items')" onmouseout="kill()">
        <img id="saLffc" src="images/edeath.gif" class="cvSelectAllImg" onmouseover="statspopup(event,'Life Forces')" onmouseout="kill()">
        <img id="saSlgm" src="images/soulgem1.jpg" class="cvSelectAllImg" onmouseover="statspopup(event,'Soul Gems')" onmouseout="kill()"><br>
        <img id="saWilk" src="images/items/arqitem1.jpg" class="cvSelectAllImg" onmouseover="statspopup(event,'Wilker Quest Items')" onmouseout="kill()">
        <img id="saWleq" src="images/items/blackkingchest.jpg" class="cvSelectAllImg" onmouseover="statspopup(event,'Wonderland Equipment')" onmouseout="kill()">
        <img id="saFndr" src="images/item_arcane.gif" class="cvSelectAllImg" onmouseover="statspopup(event,'Foundry Augments')" onmouseout="kill()"><br>
        <img id="saTrnk" src="images/items/whitetrinket.jpg" class="cvSelectAllImg" onmouseover="statspopup(event,'Trinkets')" onmouseout="kill()">
        <img id="saSprl" src="images/items/UberChallengeCore.gif" class="cvSelectAllImg" onmouseover="statspopup(event,'Spiral World Set Items')" onmouseout="kill()">
        <img id="saNbld" src="images/items/5002.gif" class="cvSelectAllImg" onmouseover="statspopup(event,'Noble Lord Set Items')" onmouseout="kill()"><br>
        <img id="saPrfc" src="images/items/PerfCore.gif" class="cvSelectAllImg" onmouseover="statspopup(event,'Perfectionist Set Items')" onmouseout="kill()">
        <img id="saExlt" src="images/items/exaltedcore.gif" class="cvSelectAllImg" onmouseover="statspopup(event,'Exalted Perfection Set Items')" onmouseout="kill()">
        <img id="saGhst" src="images/items/ghostlycore.gif" class="cvSelectAllImg" onmouseover="statspopup(event,'Ghostly Stalker Set Items')" onmouseout="kill()"><br>
        <img id="saDrgn" src="images/items/dset_weapon.gif" class="cvSelectAllImg" onmouseover="statspopup(event,'Dragon Set Items')" onmouseout="kill()">
        <img id="saChnc" src="images/items/FGRWep.gif" class="cvSelectAllImg" onmouseover="statspopup(event,'Chancellor Set Items')" onmouseout="kill()">
        <img id="saBlck" src="images/items/BHR-Weapon.gif" class="cvSelectAllImg" onmouseover="statspopup(event,'Blackhand Set Items')" onmouseout="kill()"><br>
        <img id="saAmlt" src="images/items/AOAChest.jpg" class="cvSelectAllImg" onmouseover="statspopup(event,'Amulet Chests')" onmouseout="kill()">
        <img id="saSmps" src="images/items/itema21.jpg" class="cvSelectAllImg" onmouseover="statspopup(event,'Guardian Stamps')" onmouseout="kill()">
        <img id="saTlsm" src="images/items/itemz71.jpg" class="cvSelectAllImg" onmouseover="statspopup(event,'Boss Talismen')" onmouseout="kill()"><br>
        <img id="saVoid" src="images/items/voidmakerwep.gif" class="cvSelectAllImg" onmouseover="statspopup(event,'Voidmaker Set Item')" onmouseout="kill()">
        </div></div></div>
        <div class="row mb-3">
        <div class="col-6 pr-1">
        <ul class="list-group text-left">
        <li class="list-group-item"><b>Crew Points:</b> ${points}</li>
        <li class="list-group-item"><b>Sort:</b> <a href="crew_vault?order=1">Alpha</a> / <a href="crew_vault?order=2">Newest</a></li>
        </ul>
        </div><div class="col-6 pl-1">
        <ul class="list-group text-left">
        <li class="list-group-item"><b>Items:</b> ${capacity[1]}</li>
        <li class="list-group-item"><b>Capacity:</b> ${capacity[2]}</li>
        </ul>
        </div></div>
        <input id="cvMsg" type="text" class="form-control mb-2" style="color:#FF0000 !important;">
        <div class="widget text-left mb-3">
        <h6>Items Selected: <span id="selectedCount">0</span> <span id="amuletsSelected"></span></h6>
        <div id="itemsSelectedDiv"></div>
        <div id="chaosTeleDiv"></div>
        </div>
        <div class="widget text-left mb-3">
        <h4>Award by Name</h4>
        <input id="awardByNameText" type="text" class="form-control mb-2">
        <button id="awardByName" class="btn-mm">AWARD</button><hr>
        <h4>Award Items</h4>
        <div class="mb-2" id="awardToDiv">${awardTo.outerHTML}</div>
        <button id="awardItems" class="btn-mm">AWARD</button><hr>
        <h4>Raidbound Items</h4>
        <div class="mb-2" id="rbSelDiv">${rbSel.outerHTML}</div>
        <button id="selectItems" class="btn-mm">SELECT</button><hr>
        <h4>Delete Items</h4>
        <button id="deleteItems" class="btn-mm">DELETE</button>
        </div></div></div>
        `

        var targetNodes = document.querySelectorAll('.crew_itembox_item');
        var observer = new MutationObserver(function(mutationsList) {
            mutationsList.forEach(async mutation => {
                if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
                    mutation.target.classList.toggle('item-selected');

                    const selectedItems = document.querySelectorAll('.item-selected');
                    const selectedArray = []
                    for (let i = 0; i < selectedItems.length; i++) {
                        selectedArray.push(selectedItems[i].outerHTML.replace('item-selected',''))
                    };

                    document.querySelector("#itemsSelectedDiv").innerHTML = selectedArray.join('')

                    document.querySelector("#selectedCount").innerHTML = selectedItems.length

                    if (document.querySelector("#itemsSelectedDiv").innerHTML.match('Amulet Chest')){
                        const chestIDsArray = document.querySelector("#itemsSelectedDiv").innerHTML.match(/Amulet Chest \([0-9]+\)/g)
                        let chestIDsValues = chestIDsArray.map(element => parseInt(element.match(/\d+/)[0]));
                        let chestTotal = chestIDsValues.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
                        document.querySelector("#amuletsSelected").innerHTML = `(${chestTotal} Amulets)`
                    } else {
                        document.querySelector("#amuletsSelected").innerHTML = ''
                    };

                    if (document.querySelector("#itemsSelectedDiv").innerHTML.match('Arena Teleporter')){
                        const id = document.querySelector("#itemsSelectedDiv > img").outerHTML.match(/event,'([0-9]+)'/i)[1]
                        const item = await superfetch(`item_rollover.php?id=${id}`);
                        const chars = item.match(/&nbsp;[A-Za-z0-9]+/g).map(i => (i.match(/&nbsp;([A-Za-z0-9]+)/)[1]));
                        const array = []
                        const checkChars = async (char) => {
                            const profile = await superfetch (`profile?transnick=${char}`)
                            const power = parseInt(profile.replace(/,/g,'').match(/TOTAL POWER<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]);
                            const ele = parseInt(profile.replace(/,/g,'').match(/ELEMENTAL ATTACK<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]);
                            array.push([char,power+ele])
                        };
                        await Promise.all(chars.map(checkChars));
                        const highestValueElement = array.reduce((acc, curr) => curr[1] > acc[1] ? curr : acc);
                        const bestChar = highestValueElement[0];
                        document.querySelector("#chaosTeleDiv").innerHTML = `<br><b>Arena Teleporter selected</b><br>Strongest char available: ${bestChar}`
                    };
                };
            });
        });
        targetNodes.forEach(node => { observer.observe(node, { attributes: true }) });

        document.querySelector("#awardByName").addEventListener('click', async function(){
            const name = document.querySelector("#awardByNameText").value;
            const regex = new RegExp(`<option value="([0-9]+)">${name.toLowerCase()}<\/option>`)
            const value = awardTo.outerHTML.toLowerCase().match(regex)
            if (value){
                await loadingOverlay()
                await cvAward(value[1],name);
                document.querySelector("#awardByNameText").value = '';
            } else {
                document.querySelector("#cvMsg").value = `${name} not found`
            };
        });

        document.getElementById("awardByNameText").addEventListener("keyup", function(event) {

            if (event.key === "Enter") {

                document.getElementById("awardByName").click();
            }
        });

        document.querySelector("#awardItems").addEventListener('click', async function(){
            await loadingOverlay();
            const dropdown = document.querySelector("#awardToDiv > select")
            const value = dropdown.value
            const regex = new RegExp(`<option value="${value}">(.*?)<\/option>`)
            const name = dropdown.innerHTML.match(regex)[1]
            await cvAward(value,name);
        });

        document.querySelector("#selectItems").addEventListener('click', async function(){
            const dropdown = document.querySelector("#rbSelDiv > select")
            const value = dropdown.value

            const regex = new RegExp(`<option value="${value}">(.*?)<\/option>`)
            const name = dropdown.innerHTML.match(regex)[1]

            const post = await superpost(`crew_vault`,`form-nonce=${nonce}&rbsel=${value}&selrb=Select+items`);
            if (post.match(/id="v_item_border[0-9]+" src="[^"]*" style="border:2px solid #cc0000;"/i)){
                nonce = await nonceGet();
                document.querySelector("#awardByNameText").value = name;

                const ids = post.match(/id="v_item_border[0-9]+" src="[^"]*" style="border:2px solid #cc0000;"/g).map(i => i.match(/v_item_border([0-9]+)/i)[1])

                for (let i = 0; i < ids.length; i++) {
                    const id = ids[i];
                    document.querySelector(`#v_item_border${id}`).click();
                };

            } else {
                document.querySelector("#cvMsg").value = `No raidbound items found for ${name}`
            };
        });

        document.querySelector("#deleteItems").addEventListener('click', async function(){
            const selected = selectedArray = document.querySelector("#itemsSelectedDiv").innerHTML.match(/event,'[0-9]+'/g)
            if (selected){
                const selectedArray = document.querySelector("#itemsSelectedDiv").innerHTML.match(/event,'[0-9]+'/g).map(i => `&v_selected%5B%5D=${i.match(/[0-9]+/i)}`)
                const confirm = window.confirm(`Are you sure you want to delete ${selectedArray.length} items?`);
                if (confirm){
                    const del = await superpost('crew_vault',`order=1${selectedArray.join('')}&form-nonce=${nonce}&awardto=0&rbsel=0&confirm_delete=on&delete=Delete+items`)
                    if (del){
                        nonce = await nonceGet();
                        const ids = document.querySelector("#itemsSelectedDiv").innerHTML.match(/v_item_border[0-9]+/g).map(i => i.match(/[0-9]+/i)[0])
                        document.querySelector("#selectedCount").innerHTML = '0'
                        document.querySelector("#itemsSelectedDiv").innerHTML = ''
                        for (let i = 0; i < ids.length; i++) {
                            const id = ids[i];
                            document.querySelector(`#v_item_border${id}`).remove()
                            document.querySelector(`#v_selected_${id}`).remove()
                        };
                    };
                };
            };
        });

        async function cvAward(value,name){
            const selected = selectedArray = document.querySelector("#itemsSelectedDiv").innerHTML.match(/event,'[0-9]+'/g)
            if (selected){
                const selectedArray = document.querySelector("#itemsSelectedDiv").innerHTML.match(/event,'[0-9]+'/g).map(i => `&v_selected%5B%5D=${i.match(/[0-9]+/i)}`)
                const award = await superpost('crew_vault',`order=1${selectedArray.join('')}&form-nonce=${nonce}&awardto=${value}&award=Award+Items&rbsel=0`)

                if (award.match(/<strong>Status:<\/strong> <br>Backpack full,.*?not awarded<\/div>/i)){
                    alert(`Player's backpack is full. Some items may not have been awarded. Check award log for more information`)
                    window.location = 'crew_vault'

                } else if (award){
                    nonce = await nonceGet();
                    const ids = document.querySelector("#itemsSelectedDiv").innerHTML.match(/v_item_border[0-9]+/g).map(i => i.match(/[0-9]+/i)[0])
                    document.querySelector("#cvMsg").value = `Awarded ${ids.length} items to ${name}`
                    for (let i = 0; i < ids.length; i++) {
                        const id = ids[i];
                        document.querySelector(`#v_item_border${id}`).remove()
                        document.querySelector(`#v_selected_${id}`).remove()
                    };
                    document.querySelector("#selectedCount").innerHTML = '0'
                    document.querySelector("#amuletsSelected").innerHTML = ''
                    document.querySelector("#itemsSelectedDiv").innerHTML = ''
                    await loadingOff();
                };
            } else {
                document.querySelector("#cvMsg").value = `No items selected`
            };
        };

        async function nonceGet(){
            const fetch = await superfetch("crew_vault",true)
            const nonce = fetch.match(/name="form-nonce" value="([^"]*)"/i)[1];
            return nonce;
        };

        document.querySelectorAll('.cvSelectAllImg').forEach(img => {
            img.addEventListener('click', async () => {
                let images;
                const saImgId = img.id;
                if (saImgId == "saEthl") { images = ['arheart','saveitem30','arqitem2','arqitem3','saveitem18'] };
                if (saImgId == "saNbld") { images = ['5002','5003','5004','5005','5006','5007','5008','5009','5010','5011'] };
                if (saImgId == "saSprl") { images = ['UberChallenge'] };
                if (saImgId == "saPrfc") { images = ['Perf'] };
                if (saImgId == "saExlt") { images = ['exalted'] };
                if (saImgId == "saFndr") { images = ['item_holy','item_arcane','item_shadow','item_fire','item_kinetic'] };
                if (saImgId == "saDrgn") { images = ['dset_'] };
                if (saImgId == "saLffc") { images = ['eearth','eair','ewater','efire','edeath','lifeforce_'] };
                if (saImgId == "saSlgm") { images = ['soulgem'] };
                if (saImgId == "saWilk") { images = ['itema46','itemz51','itemz110','arqitem1','storeitem4','itema52'] };
                if (saImgId == "saWleq") { images = ['InquisitorsHarpoon2','RingofWonders','redkingbelt','blackkingchest'] }
                if (saImgId == "saTrnk") { images = ['BrutalTrinket','PinkNameTrinket','DarkblueNameTrinket','OrangeNameTrinket','MysteriousTrinket','LuminousTrinket','whitetrinket','enflamedtrinket','agiletrinket'] }
                if (saImgId == "saGhst") { images = ['ghostly'] }
                if (saImgId == "saChnc") { images = ['FGR'] }
                if (saImgId == "saBlck") { images = ['BHR-'] }
                if (saImgId == "saAmlt") { images = ['AOAChest'] }
                if (saImgId == "saSmps") { images = ['itema18','itema19','itema21']}
                if (saImgId == "saTlsm") { images = ['saveitem34','itema7','itemz56','itemz10','itemz71'] }
                if (saImgId == "saVoid") { images = ['voidmaker'] }
                images.forEach(function(source) {
                    document.querySelector("#cvitems").querySelectorAll('img[src*="' + source + '"]').forEach(function(image) {
                        image.click();
                    });
                });
            });
        });

    } else {
        cvItems = document.body.innerHTML.replace(/[\n\r]/g,'').match(/<img alt="[^"]*" class="[^"]*" id="[^"]*" src="[^"]*" style="border:0px;" onmouseover="itempopup\(event,'[0-9]+'\)" onmouseout="kill\(\)" ondblclick="selectAllItem\('[0-9]+'\);kill\(\);" onclick="selectItem\('[0-9]+'\);kill\(\);">/g)
        document.querySelector("#content").innerHTML = `
        <div class="row mb-3" style="max-width:100%;">
        <div class="pr-1" style="width:50%">
        <ul class="list-group text-left">
        <li class="list-group-item"><b>Crew Points:</b> ${points}</li>
        <li class="list-group-item"><b>Sort:</b> <a href="crew_vault?order=1">Alpha</a> / <a href="crew_vault?order=2">Newest</a></li>
        </ul>
        </div><div class="pl-1" style="width:50%">
        <ul class="list-group text-left">
        <li class="list-group-item"><b>Storage:</b> ${capacity[1]} / ${capacity[2]}</li>
        <li class="list-group-item"><b>Logs:</b> <a href="crew_actionlog.php?l=Award%20Item">Awards</a> / <a href="crew_actionlog.php?l=Delete%20Item">Deleted</a></li>
        </ul>
        </div></div>
        <div style="display:inline-block; max-width: 100%;">
        ${cvItems.join('')}
        </div>
        `
    };
};

async function pointTransfer(dataPremium){
    const parentDiv = document.querySelector("#content-header-row");
    const newDiv = document.createElement("div");
    newDiv.className = "statbox widget box box-shadow col-12 form-group";
    newDiv.setAttribute('style','max-width:700px;margin-top:1rem;')
    newDiv.innerHTML = `
    <h6 style="margin-bottom:0px;">You have <b>${dataPremium.toLocaleString()}</b> transferable points and can transfer up to <b>${(dataPremium * 0.9523809523809524).toFixed(2).toLocaleString()}</b> points</h6>
    <span id="taxCalc"></span>
    `
    parentDiv.appendChild(newDiv);
    document.querySelector("#AutoNumber1 > tbody > tr:nth-child(2) > td > input:nth-child(2)").addEventListener('input', function(){
        const input = document.querySelector("#AutoNumber1 > tbody > tr:nth-child(2) > td > input:nth-child(2)").value;
        if (input == '' || input == "0"){
            document.querySelector("#taxCalc").innerHTML = ''
        } else if (input*1.05 > dataPremium){
            document.querySelector("#taxCalc").innerHTML = '<h5 style="margin-bottom:0px;margin-top:1rem;color:#FF0000;"><b>You do not have enough points</b></h5>'
        } else {
        document.querySelector("#taxCalc").innerHTML = `<h5 style="margin-bottom:0px;margin-top:1rem;">${(input*1.05).toLocaleString()} points will be transferred</h5>`
        };
    })
}


async function godstatus() {

    GM_addStyle (`
    #godStatusDiv{width:1030px;text-align:left;}
    div.godStatusTile{display:inline-block;height:250px;overflow:hidden;box-shadow: 0 0 5px rgba(0, 0, 0, 1);margin:2px;text-align:center;}
    div.godStatusTile > img{width:250px;height:250px;}
    div.godStatusText{width:220px;position:relative;left:15px;top:-175px;background:#000000;padding:15px;border-radius:15px;font-size:14px;opacity:0.9;width:220px;box-shadow: 0 0 3px rgba(0, 0, 0, 1);}
    `);

    const allRecentGodKills = document.querySelector("#content").innerHTML.match(/<a href="raidattack\.php\?raidid=[0-9]+">.*?<\/a>[\n\r].*[\n\r].*[\n\r].*[\n\r].*[\n\r].*[\n\r].*/g)

    const raids = await Promise.all(allRecentGodKills.map(async (endpoint) => {
        const godName = endpoint.match(/<a href="raidattack\.php\?raidid=[0-9]+">(.*?)<\/a>/i)[1];
        const raidId = endpoint.match(/<a href="raidattack\.php\?raidid=([0-9]+)">/i)[1];
        const raidTime = endpoint.match(/([0-9]+:[0-9]+:[0-9]+ )<\/td>/i)[1];
        const crewName = endpoint.match(/<a href="crew_profile\.php\?id=[0-9]+">(.*?)<\/a>/i)[1];
        const crewId = endpoint.match(/<a href="crew_profile\.php\?id=([0-9]+)">/i)[1];
        const data = await superfetch(endpoint.match(/raidattack\.php\?raidid=[0-9]+/i));
        const items = data.match(/<a href="#" onmouseover="popup\(event,'.*?'\)" onmouseout="kill\(\)">.*?<\/a>/i) ? data.match(/<a href="#" onmouseover="popup\(event,'.*?'\)" onmouseout="kill\(\)">.*?<\/a>/i) : `<a href="#" onmouseout="kill()">0 items</a>`;
        const totalDamage = parseInt(data.replace(/,/g, '').match(/<i>Total Attacker Damage: ([0-9]+)<\/i>/i)[1]);
        const godImgHtml = data.replace(`<img src="/assets/img/getpoints.webp">`, '').match(/^<img src="[^"]*">$/im).toString();
        return [godName, { damage: totalDamage, image: godImgHtml, crew: crewName, crewId, god: godName, raidId, time: raidTime, items: items }];
    }));
    const allGods = Object.fromEntries(raids);

    const sortedGods = Object.fromEntries(Object.entries(allGods).sort(([, a], [, b]) => b.damage - a.damage));

    let newGodStatusContent = []
    for (const [god, { damage, image, crew, crewId, raidId, time, items }] of Object.entries(sortedGods)) {
        newGodStatusContent.push(`
        <div class="godStatusTile">
        ${image}<br>
        <div class="godStatusText">
        <a href="raidattack.php?raidid=${raidId}">${god.replace(/(,|the|The|of).*/gi, '')}</a><br>
        <a href="crew_profile.php?id=${crewId}">${crew.substring(0, 20)}</a><br>
        Time: ${time}<br>
        Damage: ${damage.toLocaleString()}<br>
        ${items.toString().replace('onmouseout="kill()">','onmouseout="kill()">Found ')}
        </div>
        </div>`)
    };
    const content = newGodStatusContent.map((element, index) => (index + 1) % 4 === 0 ? element + '<br>' : element).join(' ');
    document.querySelector("#content").innerHTML = `<div id="godStatusDiv">${content}</div>`;
};


async function blacksmith(server,serverNo,rgaName,charId){
    var existingDiv = document.querySelector('.col-12.col-xl-6.mb-3.mb-xl-0');
    var newDiv = document.createElement('div');
    newDiv.innerHTML = `
        <textarea style="width:400px;margin-top:1rem;opacity:1;resize:none;font-size:14px;text-align:center;padding:10px;" id="blacksmithText" type="text" class="form-control-new mb-2" autocomplete="off">
        </textarea>
    `

    existingDiv.appendChild(newDiv);
    if (window.location.href.match(/itemid=[0-9]+/i)){
        const iid = window.location.href.match(/itemid=([0-9]+)/i)[1];
        const item = await superfetch(`item_rollover.php?id=${iid}`);
        const rarity = item.match(/height:20px;font-size:12pt;text-shadow: #\w{6} 1px 1px 2px;color:#(\w{6})/i)[1]
        const gems = 4-(item.match(/\/images\/gemslot2\.jpg/) ? item.match(/\/images\/gemslot2\.jpg/g).length : 0);
        const upgrades = await info("Cost to Gem");

        const cost = upgrades[rarity][gems] - upgrades[rarity][gems+1];

        const typeOfPoints = item.match(/\[Player Bound\]/i) ? "pb points" : "prem points"

        const regex = new RegExp(`<b>${typeOfPoints.toUpperCase()}:<\/td><td>(.*?)<\/td>`)
        const myPoints = document.querySelector("#toolbarPoints").innerHTML.match(regex)[1];

        document.querySelector("#blacksmithText").value = `It will cost ${cost} ${typeOfPoints} to gem this item\nYou have ${myPoints} ${typeOfPoints}`
    };
};


async function gladiator(charId,profile){
    if (document.body.innerHTML.match(/<h1>Gladiator of Loyalty<\/h1>/i)){

        GM_addStyle(`
        .mark-count {padding:1px;}
        .loyalty-glad-table > tbody > tr > td > img {height:20px;width:20px;margin:3px;}
        .me-row {box-shadow: inset 0 0 2px 2px rgba(255, 255, 255, 0.4);}
        .faction-img {height:30px;width:30px;margin-bottom:10px;margin-right:5px;cursor:pointer;}
        `)

        const myFaction = profile.match(/<font size="1">FACTION<\/font><\/b><\/td>\n.*?([A-Za-z]+) \(.*?\)/i)[1];

        const div = document.querySelector('.grid-container-faction');

        const parser = new DOMParser();
        const doc = parser.parseFromString(div.innerHTML, 'text/html');

        const divs = Array.from(doc.querySelectorAll('.grid-item')).map(div => div.innerHTML.trim());

        const rankArrays = [];
        let tempArray = [];
        divs.forEach((div, index) => {
            tempArray.push(div);
            if ((index + 1) % 6 === 0) {
                rankArrays.push(tempArray);
                tempArray = [];
            }
        });

        const rows = rankArrays.slice(1).map((data, index) => {

            const filteredRowData = data.filter((_, dataIndex) => dataIndex !== 1 && dataIndex !== 2);

            let newColumn =
            index < 1 && index >= 0 ? `<img src="https://torax.outwar.com/images/rfury.jpg"><img src="/images/items/triworldgladmark.png"><span class="mark-count">x25</span>` :
            index < 2 && index >= 1 ? `<img src="https://torax.outwar.com/images/rfury.jpg"><img src="/images/items/triworldgladmark.png"><span class="mark-count">x21</span>` :
            index < 3 && index >= 2 ? `<img src="https://torax.outwar.com/images/rfury.jpg"><img src="/images/items/triworldgladmark.png"><span class="mark-count">x18</span>` :
            index < 4 && index >= 3 ? `<img src="https://torax.outwar.com/images/rfury.jpg"><img src="/images/items/triworldgladmark.png"><span class="mark-count">x16</span>` :
            index < 5 && index >= 4 ? `<img src="https://torax.outwar.com/images/rfury.jpg"><img src="/images/items/triworldgladmark.png"><span class="mark-count">x15</span>` :
            index < 8 && index >= 5 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x14</span>` :
            index < 11 && index >= 8 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x13</span>` :
            index < 14 && index >= 11 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x12</span>` :
            index < 17 && index >= 14 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x11</span>` :
            index < 20 && index >= 17 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x10</span>` :
            index < 22 && index >= 20 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x9</span>` :
            index < 24 && index >= 22 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x8</span>` :
            index < 26 && index >= 24 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x7</span>` :
            index < 28 && index >= 26 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x6</span>` :
            index < 30 && index >= 28 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x5</span>` :
            index < 42 && index >= 30 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x4</span>` :
            index < 50 && index >= 42 ? `<img src="/images/items/triworldgladmark.png"><span class="mark-count">x3</span>` :
            ''

            let style = ''
            if (filteredRowData[1].match(charId)){
                style = `class="me-row"`
            };

            const rowHTML = filteredRowData.map(cellData => `<td>${cellData}</td>`).join('');
            return `<tr ${style}>${rowHTML}<td>${newColumn}</td></tr>`;
        });

        const chest = {
            Vordyn: 'images/items/vordyngladchest.png',
            Delruk: 'images/items/delrukgladchest.png',
            Alvar: 'images/items/alvargladchest.png'
        };
        const groupedRows = rankArrays.reduce((groups, rowData) => {
            if (rowData[2].match(/title=".*?"/)) {
                const faction = rowData[2].match(/title="(.*?)"/)[1];
                if (!groups[faction]) {
                    groups[faction] = [];
                }
                let img = '';
                let tier = '';
                const rank = parseInt(rowData[1].replace('.',''));
                if (rank >= 1 && rank <= 3) {
                    tier = '1.'
                    img = `<img src="${chest[faction]}">`
                } else if (rank >= 4 && rank <= 6) {
                    tier = '2.'
                    img = `<img src="${chest[faction]}">`
                } else if (rank >= 7 && rank <= 9) {
                    tier = '3.'
                    img = `<img src="${chest[faction]}">`
                } else if (rank >= 10 && rank <= 12) {
                    tier = '4.'
                    img = `<img src="${chest[faction]}">`
                } else if (rank >= 13 && rank <= 15) {
                    tier = '5.'
                    img = `<img src="${chest[faction]}">`
                }

                let style = ''
                if (rowData[3].match(charId)){
                    style = `class="me-row"`
                };

                const trElement = `<tr ${style}><td>${tier}</td>${rowData.slice(3).map(cellData => `<td>${cellData}</td>`).join('')}<td>${img}</td></tr>`;                groups[faction].push(trElement);
            }
            return groups;
        }, {});

        const factionHeaders = '<thead><tr><th>tier</th><th>player</th><th>damage</th><th>atks</th><th>prize</th></tr></thead>'
        document.querySelector("#content").innerHTML = `
        <div class="layout-px-spacing">
        <!-- Header -->
        <div class="widget-content widget-content-area text-center mb-3">
        <h1 style="margin-bottom:0rem;">Gladiator of Loyalty</h1>
        </div>
        <div class="row justify-content-center">
        <!-- Left column -->
        <div class="col-lg-6 col-md-6 col-sm-6 col-6 layout-spacing layout-spacing">
        <!-- Left column widget #1 -->
        <div class="widget-content widget-content-area text-left mb-3">
        <table class="table loyalty-glad-table">
        <thead><tr><th>rank</th><th>player</th><th>damage</th><th>atks</th><th>prize</th></tr></thead>
        ${rows.join('')}
        </table>
        </div>
        </div>
        <!-- Right column -->
        <div class="col-lg-6 col-md-6 col-sm-6 col-6 layout-spacing layout-spacing">
        <!-- Right column alvar rankings -->
        <div class="widget-content widget-content-area text-left mb-3">
        <img src="https://studiomoxxi.com/moxxibots/factions/a.png" class='faction-img' id="btnAlvar">
        <img src="https://studiomoxxi.com/moxxibots/factions/d.png" class='faction-img' id="btnDelruk">
        <img src="https://studiomoxxi.com/moxxibots/factions/v.png" class='faction-img' id="btnVordyn">
        <i>click the faction logo to see faction-specific rankings</i>
        <div id="factionRankingsDiv">
        </div>
        </div>
        </div>
        `

        document.querySelector("#factionRankingsDiv").innerHTML = `
            <table class="table loyalty-glad-table">
            ${factionHeaders}
            ${(groupedRows[myFaction] || []).join('')}
            </table>
        `

        document.querySelector("#btnAlvar").addEventListener('click', async function(){
            document.querySelector("#factionRankingsDiv").innerHTML = `
            <table class="table loyalty-glad-table">
            ${factionHeaders}
            ${(groupedRows['Alvar'] || []).join('')}
            </table>
            `
        });
        document.querySelector("#btnDelruk").addEventListener('click', async function(){
            document.querySelector("#factionRankingsDiv").innerHTML = `
            <table class="table loyalty-glad-table">
            ${factionHeaders}
            ${(groupedRows['Delruk'] || []).join('')}
            </table>
            `
        });
        document.querySelector("#btnVordyn").addEventListener('click', async function(){
            document.querySelector("#factionRankingsDiv").innerHTML = `
            <table class="table loyalty-glad-table">
            ${factionHeaders}
            ${(groupedRows['Vordyn'] || []).join('')}
            </table>
            `
        });
    };
};


async function home(profile) {


    GM_addStyle (`
    #content-header-row > div.bio.col-lg-8.col-md-8.col-sm-12.col-12.layout-spacing.layout-spacing > div.widget.widget-chart-one.mb-3{display:none;}
    #homeTiles{text-align:left;}
    img.tile-animate{box-shadow: 5px 5px 5px rgba(0, 0, 0, 1);cursor:pointer;transition: .5s ease-out;width:16.5%;height:16.5%;border-radius:5px;margin:1.5%;animation: fadeIn 1s ease-in-out forwards, tileanimate 1s infinite;}
    img.tile-still{box-shadow: 5px 5px 5px rgba(0, 0, 0, 1);cursor:pointer;transition: .5s ease-out;width:16.5%;height:16.5%;border-radius:5px;margin:1.5%;animation: fadeIn 1s ease-in-out forwards;}
    @keyframes fadeIn {from {opacity: 0;} to {opacity: 1;}}
    img.tile-still:hover{filter: saturate(250%);opacity:0.5;}
    @keyframes tileanimate{0% {filter: saturate(100%);} 50% {filter: saturate(250%); } 100% {filter: saturate(100%);}}
    .rankings-table > tbody> tr > td > img {width:50px;height:25px;}
    .rankings-table > tbody> tr > td{font-size:11px;}
    .rankings-table{height:680px;overflow:hidden;box-shadow: 0 0 5px rgba(0, 0, 0, 1);}
    #expChart > tbody > tr > td{padding:4px;font-size:10px;}
    #expChartContainer{height:1200px;overflow:auto;}
    tr.me-in-top-20{box-shadow: inset 0 0 2px 2px rgba(255, 255, 255, 0.4);}
    #homeNewsContainer{padding:26px;}
    #homeTilesContainer{padding:15px;}
    `);


    const homepageHeader = document.querySelector("#content-header-row > div.bio.col-lg-8.col-md-8.col-sm-12.col-12.layout-spacing.layout-spacing > div.widget.widget-chart-one.mb-3").innerHTML
    const charName = homepageHeader.match(/<h6 class="">(.*?)<\/h6>/i)[1];
    const charSpec = homepageHeader.match(/<span class="t-uppercontent">(.*?)<\/span>/i)[1];


    const allCast = profile.match(/<img align="absmiddle" border="0" src="[^"]*" hspace="2" width="25" height="25" alt=".*?" ONMOUSEOVER="popup\(event,'.*?',[0-9]+\)" ONMOUSEOUT="kill\(\)">/g) || [''];


    const menuLeft = document.querySelector("#content-header-row > div.bio.col-lg-8.col-md-8.col-sm-12.col-12.layout-spacing.layout-spacing");
    const firstLeftChild = menuLeft.firstChild;
    const menuRight = document.querySelector("#content-header-row > div.col-lg-4.col-md-4.col-sm-12.col-12.layout-spacing.layout-spacing");
    const firstRightChild = menuRight.firstChild;


    const headerDivContent = `
    <div id="homeHeader">
    <h3>${charName}</h3>
    ${charSpec}<br>
    <span id="factionLogo"></span>
    <hr>
    <div id="tabSkills">${allCast.join(' ')}</div>
    <b>Thank you for using MoxxiMod</b>
    </div>
    `
    const headerDiv = document.createElement('div');
    headerDiv.innerHTML = headerDivContent
    headerDiv.setAttribute('class','widget mb-3');
    menuRight.insertBefore(headerDiv, firstRightChild);

    const faction = profile.match(/<font size="1">FACTION<\/font><\/b><\/td>\n.*?([A-Za-z]+) \(.*?\)/i)[1]
    if (faction == "Vordyn"){
        document.querySelector("#factionLogo").innerHTML = `<img src="https://studiomoxxi.com/moxxibots/factions/v.png" style="height:100px;width:100px;margin:20px;">`
        GM_addStyle (`.widget,.widget-content-area{-webkit-box-shadow:0px 0px 3px 3px rgba(252,41,205,0.5);`)
    } else if (faction == "Alvar"){
        document.querySelector("#factionLogo").innerHTML = `<img src="https://studiomoxxi.com/moxxibots/factions/a.png" style="height:100px;width:100px;margin:20px;">`
        GM_addStyle (`.widget,.widget-content-area{-webkit-box-shadow:0px 0px 3px 3px rgba(0,159,255,0.5);`)
    } else if (faction == "Delruk"){
        document.querySelector("#factionLogo").innerHTML = `<img src="https://studiomoxxi.com/moxxibots/factions/d.png" style="height:100px;width:100px;margin:20px;">`
        GM_addStyle (`.widget,.widget-content-area{-webkit-box-shadow:0px 0px 3px 3px rgba(255,120,39,0.5);`)
    };


    const tilesDivContent = `
    <div class="widget-content widget-content-area text-left mb-3">
    <div id="homeTiles">
    <h3 class>Alert Tiles</h3>
    <div id="homeTilesContainer">
    <img src="https://studiomoxxi.com/moxximod/loading-gif.gif" style="height:100px;width:100px;padding:20px">
    </div>
    </div>
    </div>
    `
    const tilesDiv = document.createElement('div');
    tilesDiv.innerHTML = tilesDivContent;
    menuLeft.insertBefore(tilesDiv, firstLeftChild);



    const fetch = await superfetch('news');
    const parse = new DOMParser();
    const news = parse.parseFromString(fetch, 'text/html');
    const newsHeader = news.querySelector("#content-header-row > div > div:nth-child(1) > div.widget-header > div > div > b").innerHTML
    const newsContent = news.querySelector("#content-header-row > div > div:nth-child(1) > div.widget-content.widget-content-area.newstext").innerHTML.replace(/<br><br>[\n\r]<img border="0" src="[^"]*">/i,'')

    const newsDivContent = `
    <div class="widget-content widget-content-area text-left mb-3">
    <div id="homeNews">
    <h3 class>Outwar News</h3>
    <div id="homeNewsContainer">
    ${newsHeader}<br><br>
    ${newsContent}<br><br>
    <a href="news">More News</a>
    </div>
    </div>
    </div>
    `
    const newsDiv = document.createElement('div');
    newsDiv.innerHTML = newsDivContent;
    menuLeft.insertBefore(newsDiv, firstLeftChild);


    const parser = new DOMParser();
    const dom = parser.parseFromString(profile, 'text/html');
    const equipment = dom.querySelector("#divProfile > div:nth-child(2) > div > div > div.col-xl-4.col-md-5 > div > div:nth-child(2) > div > div").outerHTML
    const equipmentDivContent = `<h6>Equipment</h6>${equipment}`

    const rankingsEle = await superfetch('ajax/rankings.php?type=char_elepower')
    const rankingsPower = await superfetch('ajax/rankings.php?type=char_power')


    if (rankingsEle == "error"){
        document.querySelector("#homeTilesContainer").innerHTML = 'Alert tiles not available via trustee'
        return;
    };


    const rankingsDiv = document.createElement('div');
    rankingsDiv.innerHTML = `
    <h3 class>Rankings</h3>
    <div class="bio-skill-box"><div class="row"><div class="col-12 col-xl-6"><div class="row"><div class="col-12 mb-3"><div class="d-flex b-skills"> <div class="w-100">
    <h5>TOP-20 POWER</h5>
    <div class="table-responsive" id="rankings-power">
    </div></div></div></div></div></div>

    <div class="col-12 col-xl-6"><div class="row"><div class="col-12 mb-3"><div class="d-flex b-skills"><div class="w-100">
    <h5>TOP-20 ELEMENTAL</h5>
    <div class="table-responsive" id="rankings-ele">
    </div>
    `
    rankingsDiv.setAttribute('class','widget-content widget-content-area text-left mb-3');
    menuLeft.insertBefore(rankingsDiv, firstLeftChild);

    const equipmentDiv = document.createElement('div');
    equipmentDiv.innerHTML = equipmentDivContent
    equipmentDiv.setAttribute('class','widget mb-3');
    menuRight.insertBefore(equipmentDiv, firstRightChild);

    const arrayEle = rankingsEle.match(/\{"id":"[0-9]+","name":"[^"]*","pic":"[^"]*","stat":[0-9]+,/g)
    const arrayPower = rankingsPower.match(/\{"id":"[0-9]+","name":"[^"]*","stat":"[0-9]+","pic":"[^"]*",/g)

    let tableEle = ''
    let tablePower = ''
    for (let i = 0; i < 20; i++) {
        const obj = arrayEle[i]
        const id = obj.match(/"id":"([0-9]+)"/i)[1]
        const name = obj.match(/"name":"([^"]*)"/i)[1]
        const pic = obj.match(/"pic":"([^"]*)"/i)[1]
        const stat = parseInt(obj.match(/"stat":([0-9]+)/i)[1]).toLocaleString()
        if (name == charName){
            tableEle += `<tr class="me-in-top-20"><td>${i+1}</td><td><a href="profile?id=${id}">${name}</a></td><td>${stat}</td><td><img src="https://upload.outwar.com/uploaded/${pic}"></td>`
        } else {
            tableEle += `<tr><td>${i+1}</td><td><a href="profile?id=${id}">${name}</a></td><td>${stat}</td><td><img src="https://upload.outwar.com/uploaded/${pic}"></td>`
        };
    };
    for (let i = 0; i < 20; i++) {
        const obj = arrayPower[i]
        const id = obj.match(/"id":"([0-9]+)"/i)[1]
        const name = obj.match(/"name":"([^"]*)"/i)[1]
        const pic = obj.match(/"pic":"([^"]*)"/i)[1]
        const stat = parseInt(obj.match(/"stat":"([0-9]+)"/i)[1]).toLocaleString()
        if (name == charName){
            tablePower += `<tr class="me-in-top-20"><td>${i+1}</td><td><a href="profile?id=${id}">${name}</a></td><td>${stat}</td><td><img src="https://upload.outwar.com/uploaded/${pic}"></td>`
        } else {
            tablePower += `<tr><td>${i+1}</td><td><a href="profile?id=${id}">${name}</a></td><td>${stat}</td><td><img src="https://upload.outwar.com/uploaded/${pic}"></td>`
        };
    };

    document.querySelector("#rankings-ele").innerHTML = `<table class="rankings-table table table-striped">${tableEle}</table>`
    document.querySelector("#rankings-power").innerHTML = `<table class="rankings-table table table-striped">${tablePower}</table>`


    const expChart = await superfetch('expchart');
    const expChartParse = expChart.replace(/<td.*?>/g,'').replace(/,/g,'');
    const expChartArray = expChartParse.match(/[0-9]+<\/td>[\n\r][0-9]+<\/td>[\n\r][0-9]+<\/td>[\n\r][0-9]+<\/td>[\n\r][0-9]+<\/td>[\n\r]/g);
    function sortByNumericValue(str) {
        const numericValue = parseInt(str.match(/\d+(?=<\/td>)/)[0]);
        return numericValue;
    };
    expChartArray.sort((a, b) => sortByNumericValue(a) - sortByNumericValue(b));
    let expChartTable = ''
    for (let i = 0; i < expChartArray.length; i++) {
        const row = expChartArray[i]
        expChartTable += `<tr><td>${row.replace(/\n/g,'<td>').slice(0,-4)}</tr>`
    };
    const outputString = expChartTable.replace(/\d+/g, match => parseInt(match, 10).toLocaleString());
    var parentDiv = document.querySelector("#content-header-row > div.col-lg-4.col-md-4.col-sm-12.col-12.layout-spacing.layout-spacing");
    var newDiv = document.createElement("div");
    newDiv.setAttribute('style','margin-top:1rem;')
    newDiv.innerHTML = `
    <div class="widget widget-table-one mb-3">
    <h6>Experience Chart</h6>
    <div id="expChartContainer">
    <table id="expChart" class="table table-striped">
    <thead><tr><th>Lvl</th><th>Experience</th><th>SP</th><th>Atk</th><th>Hp</th></tr></thead>
    ${outputString}
    </table>
    </div>
    </div>
    <div class="widget widget-table-one mb-3">
    <button id="mmReset" class="btn-mm">RESET MOXXIMOD</button>
    </div>`
    parentDiv.appendChild(newDiv);


    if (tilesDiv.innerHTML.match('Click to max')){
        document.querySelector("#maxSupplies").addEventListener("click", maxSupplies);
    };


    document.querySelector('#mmReset').addEventListener('click',function(){
        const confirm = window.confirm("Are you sure you want to reset all MoxxiMod settings to default?");
        if (confirm) {
            var allKeys = GM_listValues();
            allKeys.forEach(function(key) {
                GM_setValue(key, "");
            });
            alert("MoxxiMod has been reset to default.");
            appsMenuClose();
        };
    });
};


async function world(profile,server){
    let roomnum = document.querySelector("#roomid_display").innerHTML;
    if (document.querySelector("#mapHtml").innerHTML){
        await worldApply(profile,server)
    };
    const targetNode = document.querySelector("#mapHtml");

    async function contentChangeCallback(mutations) {
        if (roomnum != document.querySelector("#roomid_display").innerHTML){
            roomnum = document.querySelector("#roomid_display").innerHTML
            worldApply(profile,server);
        }
    };
    const observer = new MutationObserver(contentChangeCallback);
    observer.observe(targetNode, { childList: true, subtree: true });
};

async function worldApply(profile,server){
    const profilepic = profile.match(/class="profilepic" src="([^"]*)"/i)[1]

    GM_addStyle(`
        body{overflow-y: scroll;}
        #content{display:none !important;}
        #mapTable{box-shadow: 0 0 5px rgba(255, 255, 255, 1);border-radius: 20px !important;}
        td.map-tile > div {height:44px !important;width:44px !important;}
        td.map-tile {background-size: cover !important;}
        #new-content{position:relative;width:50%;flex-grow:8;margin-top:130px;margin-bottom:0;margin-left:212px;max-width:1300px;transition: .6s;}
        img[src*="YAH.gif"] {margin-top:8px !important;height:25px;width:25px;content: url("${profilepic}") !important;border-radius:10px;box-shadow:0 5px 5px 0 rgba(0,0,0,1) !important;animation: player-icon 1s infinite;}
        @keyframes player-icon{0% {filter: saturate(100%);} 50% {filter: saturate(250%); } 100% {filter: saturate(100%);}}
        img[src*="owpath.png"] {margin-top:5px !important;height:35px;width:35px;}
        .w-3{-ms-flex: 0 0 27%;flex: 0 0 27%;max-width: 27%;}
        .w-4{-ms-flex: 46%;flex: 0 0 46%;max-width: 46%;}
        #liveWorld{width:100%;font-size:16px;cursor:pointer;font-family:monospace;height:50px;}
        #liveSearch{width:100%;font-size:16px;font-family:monospace;height:50px;}
        .mob-win{border: 1px solid #32CD32 !important;}
        .mob-loss{border: 1px solid #FF0000 !important;}
        #worldSkillsDiv > img {height: 20px;width: 20px;margin: 4px;border-radius: 5px;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);background: #000000;cursor: pointer;transition: .5s ease-out;}
        .findMobAndAtkAll {padding:2px;border-top-left-radius: inherit;border-top-right-radius:inherit;font-size:16px;font-weight:700;cursor:pointer;letter-spacing:2px;}
        #questLinks{margin-bottom:1rem;}
        #questInfoDiv{position:fixed;transform:translate(-50%, -50%);top:50%;left:50%;width:768px;height:80%;transition:opacity 0.25s ease;}
        #sb-container{display:none !important;}
        #questFrame{transition: .35s ease;height:0px;border-radius:10px;}
        img.world-directional{height:30px;width:30px;margin-right:10px;margin-left:10px;}
        #levelUpDiv{background-image: url("landing/levelupbg.jpg");}
    `)

    const map = document.querySelector("#mapHtml").innerHTML.replace(/td style/g,'td class="map-tile" style').replace('table','table id="mapTable"')
    const num = document.querySelector("#roomid_display").innerHTML
    const name = document.querySelector("#span_roomName").innerHTML.replace(/-/g,'');
    const mobs = document.querySelector("#roomDetails").innerHTML.replace(/<h6 class="[^"]*" style="[^"]*"><a rel="[^"]*" class="sbox" href="[^"]*">/g,`<h6 class="spawnTitle text-left" style="letter-spacing:inherit">`);

    const parser = new DOMParser();
    const dom = parser.parseFromString(profile, 'text/html');
    const eq = dom.querySelector("#divProfile > div:nth-child(2) > div > div > div.col-xl-4.col-md-5 > div > div:nth-child(2) > div > div").outerHTML
    const proPic = dom.querySelector('img.profilepic').outerHTML.match(/src="([^"]*)"/i)[1]

    const skills = profile.match(/<img align="absmiddle" border="0" src="[^"]*" hspace="2" width="25" height="25" alt=".*?" ONMOUSEOVER="popup\(event,'.*?',[0-9]+\)" ONMOUSEOUT="kill\(\)">/g) || ['none'];

    if (!document.querySelector("#new-content")){
        var newContent = document.createElement('div');
        newContent.id = 'new-content';
        var containerDiv = document.getElementById('container');
        var firstChild = containerDiv.firstChild;
        containerDiv.insertBefore(newContent, firstChild);
    };

    document.querySelector("#new-content").innerHTML = `
        <div class="row justify-content-center">
        <div class="w-3 col-lg-6 col-md-6 col-sm-12 col-12 layout-spacing px-1" style="min-width:355px">
        <div class="widget mb-2">
        <h5>${name} [${num}]</h5>
        <i>click on the map to move rooms<br><br></i>
        ${map}<br>
        <a href="world.php?room=11">TELEPORT TO ROOM 11</a>
        </div>
        <div class="widget mb-2" id="questHelperDiv" style="padding:10px;max-height:400px;overflow:auto;">
        <a href="javascript:void(0);" id="questHelper">QUEST HELPER</a>
        </div>
        </div>
        <div class="w-4 col-lg-6 col-md-6 col-sm-12 col-12 layout-spacing px-1">
        <div class="widget mb-2" style="padding:5px;">
        <span id="liveSpan" style="display:flex;justify-content:center;"><input id="liveWorld" type="text" class="form-control-new" autocomplete="off""></span>
        </div>
        <div class="widget mb-2" id="mobList">
        <div id="findMobDiv" class="list-group-item list-group-item-action spawnRow findMobAndAtkAll" style="width:calc(50% - 3px);display:inline-block;">FIND A MOB</div>
        <div id="atkAllDiv" class="list-group-item list-group-item-action spawnRow findMobAndAtkAll" style="width:calc(50% - 3px);display:inline-block;">ATK ALL MOBS</div>
        <span id="mobSpan">${mobs}</span>
        </div>
        </div>
        <div class="w-3 col-lg-6 col-md-6 col-sm-12 col-12 layout-spacing px-1" style="min-width:355px" id="worldRightColumn">
        <div class="widget mb-2" id="hasteDiv" style="padding:10px">
        <img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="20px" width="20px">
        </div>
        <div class="widget mb-2" id="worldSkillsDiv" style="padding:10px">
        <h6>Active Skills & Potions</h6>
        ${skills.join('')}
        </div>
        <div class="widget mb-2">
        ${eq}
        </div>
        </div>
    `

    const mapTiles = document.querySelectorAll(".map-tile");
    mapTiles[17].addEventListener('click',async function(){gotoRoom(northRoom,curRoom)});
    mapTiles[23].addEventListener('click',async function(){gotoRoom(westRoom,curRoom)});
    mapTiles[25].addEventListener('click',async function(){gotoRoom(eastRoom,curRoom)});
    mapTiles[31].addEventListener('click',async function(){gotoRoom(southRoom,curRoom)});
    mapTiles[17].style.cursor = "pointer"
    mapTiles[23].style.cursor = "pointer"
    mapTiles[25].style.cursor = "pointer"
    mapTiles[31].style.cursor = "pointer"

    const atkLinks = document.querySelectorAll("#mobSpan > ul > li > div > div > a[href*='attackid']");
    if (atkLinks.length > 0){
        const atkIds = [];
        atkLinks.forEach(function(atk){
            const atkid = atk.href.match(/attackid=[A-Za-z0-9]+/i);
            let atkUrl = `somethingelse.php?${atkid}`

            if (atk.href.match('userspawn=1')){
                atkUrl += '&userspawn=1'
            };
            atkIds.push(atkid);
            atk.href = "javascript:void(0);"
            atk.removeAttribute('target')

            atk.addEventListener('click', async function(){

                const attack = await superfetch(atkUrl,true);
                const mobName = attack.match(/var defender_name = "([^"]*)"/i)[1];
                const mobHp = parseInt(attack.match(/defender_health_start = ([0-9]+)/i)[1]);
                const mobBaseDmgTaken = (attack.match(/defender_taken\[[0-9]+\] = '[0-9]+'/g) || []).reduce((sum, match) => sum + parseInt(match.match(/'([0-9]+)'/)[1]), 0);
                const mobHolyDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'holy'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
                const mobArcnDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'arcane'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
                const mobShadDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'shadow'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
                const mobFireDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'fire'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
                const mobKinkDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'kinetic'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
                const mobChosDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'chaos'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
                const mobRemainingHp = Math.max((mobHp-mobBaseDmgTaken-mobHolyDmgTaken-mobArcnDmgTaken-mobShadDmgTaken-mobFireDmgTaken-mobKinkDmgTaken-mobChosDmgTaken),0);
                const mobPic = atk.parentNode.parentNode.parentNode.querySelector('img.spawnImage').outerHTML.match(/src="([^"]*)"/i)[1];

                let liveTxt = ''
                let liveClass;
                if (attack.match(/var successful = 1/i)){
                    liveClass = 'mob-win';
                    liveTxt += `Won vs ${mobName}`

                    if (attack.match('steps out of the shadows')){
                        window.location = 'world'
                    };

                    if (attack.match(/<b>WIN: Found .*?<\/b>/i)){
                        const item = attack.match(/<b>WIN: Found (.*?)<\/b>/i)[1]
                        liveTxt += ` found ${item}!`
                    };

                    if (attack.match(/<\/b>[0-9]+\/[0-9]+ killed<br>/i)){
                        const count = attack.match(/<\/b>([0-9]+\/[0-9]+) killed<br>/i)[1]
                        liveTxt += ` ${count} killed`
                    };
                    liveTxt += ' (click for info)'
                    atk.parentNode.parentNode.parentNode.remove();
                } else {
                    liveClass = 'mob-loss'
                    liveTxt += `Lost vs ${mobName}: ${(mobRemainingHp/mobHp*100).toFixed(2)}% (click for info)`
                };

                document.querySelector("#liveSpan").innerHTML = `<input id="liveWorld" type="text" class="${liveClass} form-control-new" autocomplete="off" value="${liveTxt}">`
                document.querySelector("#liveWorld").addEventListener('click', async function(){ await worldMobAtkInfo(attack,proPic,mobPic) });
            });
        });

        document.querySelector("#atkAllDiv").addEventListener('click', async function(){
            await loadingOverlay();
            for (let i = 0; i < atkIds.length; i++) {
                const atkid = atkIds[i];
                await superfetch(`somethingelse.php?${atkid}`);
            };
            window.location = 'world';
        });
    };
    if (mobs.length <= 58){
        document.querySelector("#liveWorld").value = "No mobs found in this room"
    };

    const qLinks = document.querySelectorAll('#mobSpan img[src="/landing/questicon.png"]');
    if (qLinks.length > 0){

        qLinks.forEach(function(q){
            const talk = q.parentNode.outerHTML.match(/href="([^"]*)"/i)[1].replace(/amp;/g,'');
            q.parentNode.href = "javascript:void(0);"
            q.addEventListener('click', async function(){
                const mob = await superfetch(talk,true);
                const quests = mob.replace(/\.php/g,'').match(/<a href="mob_talk\?id=[0-9]+&stepid=[0-9]+&userspawn=.*?&questid=[0-9]+"><img border="0" src="\/images\/button_quest_up\.gif" hspace="2" align="absmiddle"><font size="3"><b>.*?<\/b><\/font><\/a>/g).map(q => q.replace('<img border=\"0\" src=\"/images/button_quest_up.gif\" hspace=\"2\" align=\"absmiddle\">','').replace(/<a href/g,'<span class="questLink" style="cursor:pointer;" alt').replace(/<\/a>/,'</span>'));
                document.querySelector("#liveSpan").innerHTML = `
                <div id="questLinks">
                <h5>Available Quests</h5><br>
                ${quests.join('<br>')}
                </div>
                `

                const linkArray = document.querySelectorAll('.questLink');
                linkArray.forEach(function(quest){
                    quest.addEventListener('click', async function(){
                        const questLink = quest.outerHTML.match(/alt="([^"]*)"/i)[1].replace(/amp;/g,'');
                        document.querySelector("#liveSpan").innerHTML = `
                        <iframe src="${questLink}" id="questFrame" style="border:0px #ffffff none;opacity:0;" scrolling="no" frameborder="1" marginheight="0px" height="500px" width="100%"></iframe>
                        `
                        document.getElementById('questFrame').addEventListener('load', function() {

                            const iframe = document.querySelector("#questFrame");
                            if (iframe) {

                                iframe.style.opacity = '1';

                                var backLink = iframe.contentDocument.querySelector('a[href*="mob.php?id="]');
                                if (backLink) {
                                    backLink.style.display = 'none';
                                };

                                const content = iframe.contentDocument.querySelector("#content-header-row")
                                if (content){
                                    content.setAttribute('style','margin-top:0px;')
                                };

                                const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
                                iframe.style.height = iframeDocument.body.scrollHeight + 'px';
                            };
                        });
                    });
                });
            });
        });
    };

    const haste = await superfetch('skills_info.php?id=3024');

    if (haste.match(/value="Cast Skill"/i)){
        document.querySelector("#hasteDiv").innerHTML = `<a href="javascript:void(0);" id="castHaste">CASTE HASTE</a>`
        document.querySelector("#castHaste").addEventListener('click', async function(){
            await superpost('cast_skills.php?C=4','castskillid=3024&cast=Cast+Skill');
            const profileRefresh = await superfetch('profile',true);
            const skillsRefresh = profileRefresh.match(/<img align="absmiddle" border="0" src="[^"]*" hspace="2" width="25" height="25" alt="[^"]*" ONMOUSEOVER="popup\(event,'[^']*',[0-9]+\)" ONMOUSEOUT="kill\(\)">/g) || ['none'];
            document.querySelector("#worldSkillsDiv").innerHTML = `
                <h6>Active Skills & Potions</h6>
                ${skillsRefresh.join('')}
            `
        });

    } else if (haste.match(/This skill is recharging\. [0-9]+ minutes remaining\./i)){
        const time = haste.match(/This skill is recharging\. ([0-9]+) minutes remaining\./i)[1]
        document.querySelector("#hasteDiv").innerHTML = `Haste is ready in ${time} minutes`

    } else if (haste.match(/You have not learned this skill yet/i)){
        document.querySelector("#hasteDiv").innerHTML = `Haste is not trained`
    };

    document.querySelector("#questHelper").addEventListener('click', function(){
        const quests = document.querySelector(".widget.widget-chart-two").innerHTML
        document.querySelector("#questHelperDiv").innerHTML = quests.replace(/<div id="mobsearch" style="font-weight: bold; text-align: center; margin-top: 10px;"><a id="[^"]*" href="#"><img src="[^"]*" onmouseover="[^"]*" onmouseout="[^"]*" border="0"><\/a><\/div>/i,'').replace(/<h5 class="">QUEST HELPER <\/h5>/i,'');
    });

    document.querySelector("#findMobDiv").addEventListener('click', function(){

        document.querySelector("#liveSpan").innerHTML = `
        <input id="liveSearch" type="text" class="form-control-new" autocomplete="off" placeholder="Enter mob name...">
        <button class="btn-mm" id="mobSearchBtn">SEARCH</button>
        `
        document.querySelector("#liveSearch").select();

        document.querySelector("#mobSearchBtn").addEventListener('click', worldMobSearch);
        document.querySelector("#liveSearch").addEventListener("keydown", function(event) { if (event.key === "Enter") { worldMobSearch() } });

        async function worldMobSearch(){
            const searchInput = document.querySelector("#liveSearch").value.replace(/ /g,'+');
            console.log(`https://${server}.outwar.com/mob_search.php?searchterm=${searchInput}`);
            const mobSearch = await superfetch(`https://${server}.outwar.com/mob_search.php?searchterm=${searchInput}`);
            document.querySelector("#liveSpan").innerHTML = mobSearch.replace(/href/g,'alt');
            const searchResults = document.querySelectorAll("#return_data > p > a");
            searchResults.forEach(async r => {
                r.setAttribute('style','cursor:pointer;')
                r.addEventListener('click', async function(){
                    const apply = r.outerHTML.match(/alt="([^"]*)"/i)[1];
                    await superfetch(apply);
                    window.location = 'world';
                });
            });
        };
    });

    var levelup = window.getComputedStyle(document.querySelector("#levelup")).getPropertyValue("display");
    if (levelup == "block"){
        var worldRightColumn = document.getElementById("worldRightColumn");
        var newDiv = document.createElement("div");
        newDiv.classList.add('widget');
        newDiv.classList.add('mb-2');
        newDiv.id = "levelUpDiv"
        newDiv.innerHTML = `
            <img src="landing/levelupcenter.jpg" style="height:100%;width:100%;border-radius:8px;cursor:pointer;" id="lvlUpBtn">
        `;
        worldRightColumn.insertBefore(newDiv, worldRightColumn.firstChild);
        document.querySelector("#lvlUpBtn").addEventListener('click',async function(){
            const check = confirm('Are you sure you want to level up?');
            if (check){
                await superfetch('levelup');
                window.location = 'world';
            };
        });
    };
};


async function worldMobAtkInfo(attack,proPic,mobPic){

    GM_addStyle(`
        #container{transition: opacity 0.25s ease;}
        #atkInfoDiv{position:fixed;transform:translate(-50%, -25%);top:25%;left:50%;width:768px;height:80%;transition:opacity 0.25s ease;}
        .atk-info-widget{width:45%;display:inline-block;margin:1rem;height:100%;overflow:auto;}
        img.info-img{width:300px;height:150px;box-shadow: 0 0 5px rgba(255, 255, 255, 1);}
    `)

    const plrHp = parseInt(attack.match(/var attacker_health_start = ([0-9]+)/i)[1]);
    const mobHp = parseInt(attack.match(/var defender_health_start = ([0-9]+)/i)[1]);
    const plrBaseDmgTaken = (attack.match(/attacker_taken\[[0-9]+\] = '[0-9]+'/g) || []).reduce((sum, match) => sum + parseInt(match.match(/'([0-9]+)'/)[1]), 0);
    const plrHolyDmgTaken = (attack.match(/attacker_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'holy'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const plrArcnDmgTaken = (attack.match(/attacker_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'arcane'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const plrShadDmgTaken = (attack.match(/attacker_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'shadow'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const plrFireDmgTaken = (attack.match(/attacker_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'fire'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const plrKinkDmgTaken = (attack.match(/attacker_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'kinetic'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const plrChosDmgTaken = (attack.match(/attacker_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'chaos'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const plrRemainingHp = Math.max((plrHp-plrBaseDmgTaken-plrHolyDmgTaken-plrArcnDmgTaken-plrShadDmgTaken-plrFireDmgTaken-plrKinkDmgTaken-plrChosDmgTaken),0);
    const mobBaseDmgTaken = (attack.match(/defender_taken\[[0-9]+\] = '[0-9]+'/g) || []).reduce((sum, match) => sum + parseInt(match.match(/'([0-9]+)'/)[1]), 0);
    const mobHolyDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'holy'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const mobArcnDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'arcane'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const mobShadDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'shadow'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const mobFireDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'fire'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const mobKinkDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'kinetic'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const mobChosDmgTaken = (attack.match(/defender_elemental_taken\[[0-9]+\]\[[0-9]+\] = new Damage\([0-9]+, 'chaos'\)/g) || []).reduce((sum, match) => sum + parseInt(match.match(/\(([0-9]+)/)[1]), 0);
    const mobRemainingHp = Math.max((mobHp-mobBaseDmgTaken-mobHolyDmgTaken-mobArcnDmgTaken-mobShadDmgTaken-mobFireDmgTaken-mobKinkDmgTaken-mobChosDmgTaken),0);
    const plrBLocks = attack.match(/attacker_taken\[[0-9]+\] = 'block'/) ? attack.match(/attacker_taken\[[0-9]+\] = 'block'/g).length : 0;

    const parser = new DOMParser();
    const dom = parser.parseFromString(attack, 'text/html');
    const factionBoxLeft1 = dom.querySelector('.float-div-left.faction-box-1');
    const factionBoxRight1 = dom.querySelector('.float-div-right.faction-box-1');
    const myLoyalty = factionBoxLeft1 ? parseInt(factionBoxLeft1.innerHTML.match(/([0-9]+) \/ [0-9]+/i)[1]) : 0;
    const maxLoyalty = factionBoxLeft1 ? parseInt(factionBoxLeft1.innerHTML.match(/[0-9]+ \/ ([0-9]+)/i)[1]) : 0;
    const multiplier = factionBoxRight1 ? parseInt(factionBoxRight1.innerHTML.match(/[0-9]+/i)) * 0.01 : 0;
    const loyalty = `${(myLoyalty * multiplier * 100)}% / ${(maxLoyalty * multiplier * 100)}%`

    const content = `
        <div class="widget atk-info-widget">
        <center><img src="${proPic}" class="info-img"></center><br>
        <table class="table table-striped mb-3">
        <tr><td>Starting Hit Points</td><td>${plrHp.toLocaleString()}</td></tr>
        <tr><td>Base Damage Taken</td><td>${plrBaseDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#00FFFF">Holy Damage Taken</font></td><td>${plrHolyDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#FFFF00">Arcane Damage Taken</font></td><td>${plrArcnDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#7e01bc">Shadow Damage Taken</font></td><td>${plrShadDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#FF0000">Fire Damage Taken</font></td><td>${plrFireDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#00FF00">Kinetic Damage Taken</font></td><td>${plrKinkDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#f441be">Chaos Damage Taken</font></td><td>${plrChosDmgTaken.toLocaleString()}</td></tr>
        <tr><td>Hit Points Remaining</td><td>${plrRemainingHp.toLocaleString()}</td></tr>
        <tr><td>Successful Blocks</td><td>${plrBLocks.toLocaleString()}</td></tr>
        <tr><td>Faction Bonus</td><td>${loyalty}</td></tr>
        </table>
        </div>
        <div class="widget atk-info-widget">
        <center><img src="${mobPic}" class="info-img"></center><br>
        <table class="table table-striped">
        <tr><td>Starting Hit Points</td><td>${mobHp.toLocaleString()}</td></tr>
        <tr><td>Base Damage Taken</td><td>${mobBaseDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#00FFFF">Holy Damage Taken</font></td><td>${mobHolyDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#FFFF00">Arcane Damage Taken</font></td><td>${mobArcnDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#7e01bc">Shadow Damage Taken</font></td><td>${mobShadDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#FF0000">Fire Damage Taken</font></td><td>${mobFireDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#00FF00">Kinetic Damage Taken</font></td><td>${mobKinkDmgTaken.toLocaleString()}</td></tr>
        <tr><td><font color="#f441be">Chaos Damage Taken</font></td><td>${mobChosDmgTaken.toLocaleString()}</td></tr>
        <tr><td>Hit Points Remaining</td><td>${mobRemainingHp.toLocaleString()}</td></tr>
        </table>
        </div>
        <a href="javascript:void(0);" id="atkInfoClose">close</a>
    `

    document.querySelector("#container").setAttribute('style','opacity:0.1;')
    let newDiv = document.createElement("div");
    newDiv.id = "atkInfoDiv";
    newDiv.innerHTML = content
    document.body.appendChild(newDiv);

    document.querySelector("#atkInfoClose").addEventListener('click', async function(){
        document.querySelector("#container").setAttribute('style','opacity:1;');
        document.querySelector("#atkInfoDiv").remove();
    });
};


async function myaccount(server){
    let serverSwitch;
    let serverSwitchNo;
    if (server == "torax"){
        serverSwitch = "sigil"
        serverSwitchNo = "1"
    };
    if (server == "sigil"){
        serverSwitch = "torax"
        serverSwitchNo = "2"
    };
    if (document.URL.match("myaccount")){
        document.querySelector("#content-header-row > div > div > a:nth-child(3)").setAttribute('style','display:none')
        document.querySelector("#content-header-row > div > div > a.btn.btn-warning.mb-2.mr-2.float-right").setAttribute('style','display:none')
        document.querySelector("#content-header-row > div > div > a.btn.btn-success.mb-2.mr-2.float-right").setAttribute('style','display:none')
        document.querySelector("#content-header-row > div > div > hr").setAttribute('style','display:none')
    };
    document.querySelector("#rga_ul").outerHTML = `
    <a href="myaccount"><button class="btn-mm mb-3">CHARACTERS</button></a>
    <a href="accountinfo"><button class="btn-mm mb-3">ACCOUNT</button></a>
    <a href="support"><button class="btn-mm mb-3">SUPPORT</button></a>
    <a href="editcharacters.php?page=1"><button class="btn-mm mb-3">CREATE</button></a>
    <a href="editcharacters.php?page=2"><button class="btn-mm mb-3">DELETE</button></a>
    <a href="editcharacters.php?page=3"><button class="btn-mm mb-3">TRUSTEES</button></a>
    <a href="https://torax.outwar.com/myaccount.php?ac_serverid=${serverSwitchNo}"><button class="btn-mm mb-3">SWITCH TO ${serverSwitch.toUpperCase()}</button></a><br>
    <div id="rgaMaxRage"><img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="30px" width="30px"></div>
    `
    myaccountTotals();
}

async function myaccountTotals(){

    if (document.URL.match("myaccount")){
        const ajax = await superfetch('ajax/accounts.php');
        const charids = ajax.match(/"id":"[0-9]+"/g).map(i => i.match(/[0-9]+/));

        let totMr = 0;
        let totPower = 0;
        let totEle = 0;
        let totChaos = 0;
        let totRpt = 0;

        const getCharInfo = async (id) => {
            const profile = await superfetch(`profile?suid=${id}`);
            const mr = parseInt(profile.match(/Maximum:<\/b><\/td><td>(.*?)<\/td><\/tr>/i)[1].replace(/,/g,''));
            totMr += mr;
            const power = parseInt(profile.match(/TOTAL POWER.*[\n\r].*<font size="2">(.*)<\/font><\/b><\/td>/i)[1].replace(/,/g,''));
            totPower += power;
            const ele = parseInt(profile.match(/ELEMENTAL ATTACK.*[\n\r].*<font size="2">(.*)<\/font>/i)[1].replace(/,/g,''));
            totEle += ele;
            const chaos = parseInt(profile.match(/CHAOS DAMAGE.*[\n\r].*<font size="2">(.*)<\/font>/i)[1].replace(/,/g,''));
            totChaos += chaos;
            const rpt = parseInt(profile.match(/<p class="top-rage" ONMOUSEOVER="statspopup\(event,'<tr><td><b>Per Turn:<\/b><\/td><td>(.*?)<\/td>/i)[1].replace(/,/g,''));
            totRpt += rpt;
        };
        await Promise.all(charids.map(getCharInfo));
        const html = `
        <div class="row" style="justify-content:center;">
        <ul class="list-group text-left" style="margin-right:0.5rem;width:180px;">
        <li class="list-group-item"><b>TOTAL POWER</b></li>
        <li class="list-group-item">${totPower.toLocaleString()}</li>
        </ul>
        <ul class="list-group text-left" style="margin-right:0.5rem;width:180px;">
        <li class="list-group-item"><b>TOTAL ELEMENTAL</b></li>
        <li class="list-group-item">${totEle.toLocaleString()}</li>
        </ul>
        <ul class="list-group text-left" style="margin-right:0.5rem;width:180px;">
        <li class="list-group-item"><b>TOTAL CHAOS</b></li>
        <li class="list-group-item">${totChaos.toLocaleString()}</li>
        </ul>
        <ul class="list-group text-left" style="margin-right:0.5rem;width:180px;">
        <li class="list-group-item"><b>TOTAL RPT</b></li>
        <li class="list-group-item">${totRpt.toLocaleString()}</li>
        </ul>
        <ul class="list-group text-left" style="margin-right:0.5rem;width:180px;">
        <li class="list-group-item"><b>TOTAL MAX RAGE</b></li>
        <li class="list-group-item">${totMr.toLocaleString()}</li>
        </ul>
        </div>
        `
        document.querySelector("#rgaMaxRage").innerHTML = html;
    } else {
        document.querySelector("#rgaMaxRage").remove();
    };
}


async function raidResults(){

    GM_addStyle(`
    #moxxiResults > thead > tr > th:nth-child(1){display:none;}
    #moxxiResults > tbody > tr > td:nth-child(1){display:none;}
    `)

    const crewId = document.body.innerHTML.match(/name="crewid" value="([0-9]+)"/i)[1]
    document.querySelector("#content-header-row > table > tbody > tr > td > form").outerHTML = `
    <center>
    <a href="crew_raidresults.php?crewid=${crewId}&moxximod"><button class="btn-mm">Moxximod raid results</button></a>&nbsp;
    <form method="get" style="display:inline-block">
    <input type="submit" class="btn-mm" name="all_results" value="Display all raid results">&nbsp;
    <input type="submit" class="btn-mm" name="wins" value="Display only victorious raids">&nbsp;
    <input type="submit" class="btn-mm" name="most_recent" value="Display most recent raids">
    <input type="hidden" name="crewid" value="${crewId}">
    </form>
    </center><hr>
    `
    if (document.URL.match(/crew_raidresults\.php\?crewid=[0-9]+&moxximod/i)){

        document.querySelector("#content-header-row > table > tbody > tr > td > div").setAttribute('style','display:none;');
        const headerDiv = document.querySelector("#content-header-row > div.col-12.layout-spacing")
        if (headerDiv){
            document.querySelector("#content-header-row > div.col-12.layout-spacing").setAttribute('style','display:none;')
        }

        const oldTable = document.querySelector("#content-header-row > table");
        const newElement = document.createElement("div");
        newElement.classList.add('widget')
        newElement.innerHTML = `
        <table id="moxxiResults" class="table table-striped sortable">
        <thead><tr><th>Position</th><th>Time</th><th>Raid</th><th>Chars</th><th>Result</th><th>Damage</th><th>Reg Block</th><th>Ele Block</th><th>Shield</th><th>Loyalty</th><th>Sin</th><th>Loot</th></tr></thead>
        <tbody></tbody>
        </table>
        `;
        oldTable.insertAdjacentElement("afterend", newElement);

        let data = [];
        const raidsArray = document.querySelectorAll("#content-header-row > table > tbody > tr > td > div > center > div > table > tbody > tr");
        const buildTable = async (item,index) => {
            const row = item.innerHTML;
            const raidPosition = index + 1
            const raidTime = row.match(/[0-9]+:[0-9]+/i);
            const raidAttackers = parseInt(row.match(/<td align="left" valign="top">([0-9]+)<\/td>/i)[1]);
            const raidResult = row.match(/<font color="[^"]*"><b>.*?<\/b><\/font>/i);
            const raidId = row.match(/raidid=([0-9]+)/i)[1];
            const raidName = row.match(/>.*?</g)[1].toString().match(/>(.*?)</i)[1].replace(/(,.*|of.*|The|the.*)/g, '');
            const raidFetch = await superfetch(`raidattack.php?raidid=${raidId}`);
            const raidDamage = parseInt(raidFetch.replace(/,/g, '').match(/<i>Total Attacker Damage: ([0-9]+)<\/i>/i)[1]);
            const raidAttacks = raidFetch.match(/Base: [0-9]+/g).length;
            const raidEleblock = raidFetch.match(/images\/block2\.jpg/g) ? Math.ceil((raidFetch.match(/images\/block2\.jpg/g).length)/raidAttacks*100) : 0;
            const raidRegblock = raidFetch.match(/images\/block\.jpg/g) ? Math.ceil((raidFetch.match(/images\/block\.jpg/g).length)/raidAttacks*100) : 0;
            const raidDied = raidFetch.match(/images\/dead\.jpg/g) ? (raidFetch.match(/images\/dead\.jpg/g).length) : 0;
            const raidShield = raidFetch.match(/items\/[A-Za-z]+_ele_shield\.jpg/g) ? Math.ceil((raidFetch.match(/items\/[A-Za-z]+_ele_shield\.jpg/g).length) / raidAttacks * 100) : 0;
            const raidItems = (raidFetch.match(/<a href="#" onmouseover="popup\(event,'<b>(.*?)<\/b>'\)" onmouseout="kill\(\)">.*?<\/a>/i) || ['',''])[1];
            const alvarLoyalty = raidFetch.match(/Alvar Loyalty \/ Maximum Loyalty.*?[\n\r].*?/i) ? raidFetch.match(/Alvar Loyalty \/ Maximum Loyalty.*?[\n\r].*/i) : "0/0";
            const delrukLoyalty = raidFetch.match(/Delruk Loyalty \/ Maximum Loyalty.*?[\n\r].*?/i) ? raidFetch.match(/Alvar Loyalty \/ Maximum Loyalty.*?[\n\r].*/i) : "0/0";
            const vordynLoyalty = raidFetch.match(/Vordyn Loyalty \/ Maximum Loyalty.*?[\n\r].*?/i) ? raidFetch.match(/Alvar Loyalty \/ Maximum Loyalty.*?[\n\r].*/i) : "0/0";
            const raidLoyalty = parseInt(alvarLoyalty.toString().match(/([0-9]+)\/[0-9]+/i)[1])+parseInt(delrukLoyalty.toString().match(/([0-9]+)\/[0-9]+/i)[1])+parseInt(vordynLoyalty.toString().match(/([0-9]+)\/[0-9]+/i)[1])
            const raidMaxloyalty = parseInt(alvarLoyalty.toString().match(/[0-9]+\/([0-9]+)/i)[1])+parseInt(delrukLoyalty.toString().match(/[0-9]+\/([0-9]+)/i)[1])+parseInt(vordynLoyalty.toString().match(/[0-9]+\/([0-9]+)/i)[1])
            const raidSin = (raidFetch.match(/color:#CC0000;"><b>(.*?)<\/b>/i) || [])[1] === "0" ? "YES" : "NO";
            data.push(rowData = {
                position: raidPosition,
                time: raidTime,
                name: `<a href="raidattack.php?raidid=${raidId}">${raidName}</a>`,
                attackers: `${raidAttackers} (🕱${raidDied})`,
                result: raidResult,
                damage: raidDamage.toLocaleString(),
                regblock: `${raidRegblock}%`,
                eleblock: `${raidEleblock}%`,
                shield: `${raidShield}%`,
                loyalty: `${raidLoyalty}/${raidMaxloyalty}`,
                sin: raidSin,
                items: raidItems
            });
        };
        await Promise.all(Array.from(raidsArray).slice(1).map((raid, index) => buildTable(raid, index)));

        data.sort((a, b) => a.position - b.position);
        data.forEach(rowData => {
            const rowElement = document.querySelector("#moxxiResults > tbody").insertRow();
            rowElement.innerHTML = Object.values(rowData).map(value => `<td>${value}</td>`).join('');
        });

        await sortableTables();
    };
};


async function changeFaction(profile){

    document.querySelector("#content-header-row > div > h1").remove();

    const rightContent = document.querySelector("#content-header-row > div > div > div:nth-child(2)");
    const completedCodex = document.querySelector("#content-header-row > div > div > div > div.mt-3 > div > div.widget-content.widget-content-area").innerHTML;
    const completedArray = completedCodex.match(/Triworld Codex Chapter [0-9]+/g) || [];
    const imgArray = [];
    for (let i = 0; i < completedArray.length; i++) {
        imgArray.push(`<img src="images/items/tiupgrade${completedArray[i].match(/[0-9]+/i)}.png" style="margin:5px;box-shadow: 0 0 3px rgba(0, 0, 0, 0.5)">`);
    };
    rightContent.outerHTML = `
    <div class="col-12 col-md-8">
    <div class="widget mb-3"><h3>COMPLETED CODEX</h3>${imgArray.join('')}</div>
    <div class="widget mb-3"><h3>LOYALTY RANKINGS</h3>
    <div id="loyaltyRankings"><img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="90px" width="90px"></div>
    </div>
    <div class="widget">
    <h3>FACTION LOYALTY</h3><p>
    Players can increase their loyalty with each faction (up to a maximum of 10) by completing Catalyst tasks provided by the Alvar Emissary, Delruk Emissary and Vordyn Emissary. Completing these tasks will award a Proven Loyalty item, which can be exchanged with Artel, Dumar or Valka to permanently increase your loyalty with that faction. Secondary rewards such as augments are also earned by increasing loyalty. The first 2 catalyst quests have been added with this update, with the remaining 8 to be released with future updates. While the Catalyst of Evolution is playerbound, all other catalysts will be tradeable.<p>
    Increasing your loyalty with each faction can provide bonus damage for yourself vs mobs and for all members vs raids. The bonus damage amount is determined by the effect % each encounter has, multiplied by the amount of maximum loyalty that takes effect during the encounter. Loyalty will only take effect through your current active faction.<p>
    In addition to bonus damage, loyalty can also be used to increase the power of your Triworld Influence skill, which is earned by completing the Faction Initiations quest. The power of this skill is determined by the amount of codexes collected, increased by up to 100% based on your highest faction loyalty (10% per loyalty). Codexes can be found from expansion related content which players need to discover, with 29 being added with this initial update out of the eventual total of 50. While codex 1-10 are playerbound, all other codexes will be tradeable.<p>
    </div>
    </div>
    `

    const leftContent = document.querySelector("#content-header-row > div > div > div:nth-child(1)")
    leftContent.outerHTML = `
    <div class="col-12 col-md-4">
    <div class="widget mb-3" id="factionLogo">test</div>
    <div class="widget mb-3"><h3>CHANGE FACTION</h3>${leftContent.innerHTML}</div>
    <div class="widget">
    <h3>FACTIONS</h3><p>
    <font color="#f6b861">The <b>Delruk</b> Alliance was formed by members of Diamond City and other nearby lands. They focus on base attack and vile damage.</font><p>
    <font color="#b7d9fb">The <b>Alvar</b> Liberation was formed by the survivors of the Astral Dimension war. They focus on original elemental damages.</font><p>
    <font color="#ffb7f1">The <b>Vordyn</b> Rebellion was formed on Veldara during the reign of Thanox. They focus on chaos damage.</font><p>
    Factions work similar to classes, with each character being able to choose one of 3 options. Each character is able to change faction once per month for free via the Change Faction page (also linked via the character menu) and the free faction change timer resets at the start of every month, however changing faction more than once per month will require a Faction Change item. Unlike classes, bonuses for being in each faction are not initially provided via direct stats, instead they provide access to faction specific content and activate your Faction Loyalty. While this initial update focuses primarily on the loyalty system and damage bonuses, content including level 95 enhancements will be added in the future focusing on faction specific stats.<p>
    </div>
    </div>
    `

    const faction = profile.match(/<font size="1">FACTION<\/font><\/b><\/td>\n.*?([A-Za-z]+) \(.*?\)/i)[1];
    if (faction == "Vordyn"){
        document.querySelector("#factionLogo").innerHTML = `<img src="https://studiomoxxi.com/moxxibots/factions/v.png" style="height:200px;width:200px;margin:20px;">`
        GM_addStyle (`.widget,.widget-content-area{-webkit-box-shadow:0px 0px 3px 3px rgba(252,41,205,0.5);`)
    } else if (faction == "Alvar"){
        document.querySelector("#factionLogo").innerHTML = `<img src="https://studiomoxxi.com/moxxibots/factions/a.png" style="height:200px;width:200px;margin:20px;">`
        GM_addStyle (`.widget,.widget-content-area{-webkit-box-shadow:0px 0px 3px 3px rgba(0,159,255,0.5);`)
    } else if (faction == "Delruk"){
        document.querySelector("#factionLogo").innerHTML = `<img src="https://studiomoxxi.com/moxxibots/factions/d.png" style="height:200px;width:200px;margin:20px;">`
        GM_addStyle (`.widget,.widget-content-area{-webkit-box-shadow:0px 0px 3px 3px rgba(255,120,39,0.5);`)
    } else {
        document.querySelector("#factionLogo").innerHTML = "No faction selected"
    }
    document.querySelector("#content-header-row > div > div > div:nth-child(1) > div.widget.mb-3 > h4").outerHTML = "Free faction change every calendar month"

    document.querySelector("#content-header-row > div > div > div:nth-child(1) > div.widget.mb-3 > div.mt-3").remove();
    document.querySelector(".clock-builder-output.flip-clock-small-wrapper").remove();

    document.querySelector("#content-header-row > div > div > div:nth-child(1) > div.widget.mb-3 > form > button").setAttribute('style','margin-bottom:1rem;')

    factionRankings();
};

async function factionRankings(){

    GM_addStyle(`
        table.alvar-rankings > tbody > tr > th {color:#b7d9fb;}
        table.delruk-rankings > tbody > tr > th {color:#f6b861;}
        table.vordyn-rankings > tbody > tr > th {color:#ffb7f1;}
    `)

    const powerRankings = await superfetch('ajax/rankings.php?type=char_power');
    const idArray = powerRankings.match(/"id":"[0-9]+"/g).map(i => i.match(/[0-9]+/));
    const rankings = {
        alvar: [],
        delruk: [],
        vordyn: []
    };
    const profiles = async (i) => {
        const profile = await superfetch(`profile?id=${i}`);
        const name = profile.match(/<font size="3">(.*?)<\/font>/i)[1];
        const faction = (profile.match(/<font size="1">FACTION<\/font><\/b><\/td>\n.*?([A-Za-z]+) \(.*?\)/i) || ['None','None'])[1];
        if (faction != "None"){
            const loyalty = parseInt((profile.match(/<font size="1">FACTION<\/font><\/b><\/td>\n.*?[A-Za-z]+ \((.*?)\)/i) || ['0','0'])[1]);
            rankings[faction.toLowerCase()].push({name:name,level:loyalty});
        };
    }
    await Promise.all(idArray.map(profiles));

    for (var key in rankings) {
        if (rankings.hasOwnProperty(key)) {

            rankings[key].sort((a, b) => b.level - a.level);
            rankings[key] = rankings[key].slice(0, 15);
        };
    };
    var alvarTable = '<table class="rankings-table table table-striped alvar-rankings"><tr><th><img src="https://studiomoxxi.com/moxxibots/factions/a.png" height="15px" width="15px"></th><th>ALVAR</th><th>LVL</th></tr>' + rankings.alvar.map((obj, index) => `<tr><td>${index + 1}</td><td width="180px">${obj.name}</td><td>${obj.level}</td></tr>`).join('') + '</table>';
    var delrukTable = '<table class="rankings-table table table-striped delruk-rankings"><tr><th><img src="https://studiomoxxi.com/moxxibots/factions/d.png" height="15px" width="15px"></th><th>DELRUK</th><th>LVL</th></tr>' + rankings.delruk.map((obj, index) => `<tr><td>${index + 1}</td><td width="180px">${obj.name}</td><td>${obj.level}</td></tr>`).join('') + '</table>';
    var vordynTable = '<table class="rankings-table table table-striped vordyn-rankings"><tr><th><img src="https://studiomoxxi.com/moxxibots/factions/v.png" height="15px" width="15px"></th><th>VORDYN</th><th>LVL</th></tr>' + rankings.vordyn.map((obj, index) => `<tr><td>${index + 1}</td><td width="180px">${obj.name}</td><td>${obj.level}</td></tr>`).join('') + '</table>';
    document.querySelector("#loyaltyRankings").innerHTML = `
    <div style="display:inline-block">
    ${alvarTable}</div>
    <div style="display:inline-block">
    ${delrukTable}</div>
    <div style="display:inline-block">
    ${vordynTable}</div>
    <br><i>Loyalty rankings only include players who rank top-100 for power. Other players may have a higher loyalty level but will not appear on loyalty rankings
    `
};


async function crewProfile(){

    GM_addStyle (`
    .crew-profile-pic{box-shadow: 5px 5px 5px rgba(0, 0, 0, 1);width:100%;border-radius:6px;display:inline-block;}
    #nativeMemberTable{max-height:533px;overflow:auto;}
    #crewMemberDiv{width:100%;text-align:left;display:none;margin-top:15px;}
    #crewMemberTable > tbody > tr > td > img{width:30px;height:30px;display:inline-block;border-radius:10px;}
    .button-container{display:inline-block;}
    #scrollButtons > center > a{padding:10px;font-size:16px;}
    #scrollButtons{padding-left:10px;padding-bottom:10px;padding-right:10px;}
    #actionSpace > img{margin:4px;padding:4px;box-shadow: 5px 5px 5px rgba(0, 0, 0, 1);width:40px;height:40px;border: 2px inset;}
    #actionSpace{overflow-y:auto;overflow-x:hidden;max-height:250px;}
    #crewMemberTable{height:100%;overflow:hidden;box-sizing: border-box;}
    `);

    const crewName = document.body.innerHTML.match(/<h2>(.*?)<\/h2>/i)[1]
    const crewPic = (document.body.innerHTML.match(/<img src="([^"]*)" width="[0-9]+" height="[0-9]+">/i) || ['','images/logodefault.gif'])[1]
    const crewUpgrades = document.body.innerHTML.match(/<img border="0" src="[^"]*" onmouseover="popup\(event,'<div style=&quot;width:200px&quot;><b>.*? \(Level [0-9]+\/[0-9]+ \+[0-9]+\)<\/b><br>.*?<\/div>','808080'\)" ;="" onmouseout="kill\(\)">/g)
    const crewStones = document.body.innerHTML.match(/<img style="border:2px inset;" src="[^"]*" onmouseover="[^"]*" ;="" onmouseout="kill\(\)">/g) || [];
    const crewAllies = document.body.innerHTML.replace(/[\n\r]/g,'').replace(/col-6/g,'col-4').match(/(<h5 class="card-title">CREW ALLIES<\/h5>.*?)<h5 class="card-title">CREW ENEMIES<\/h5>/i)[1];
    const crewMembers = document.body.innerHTML.match(/<td><a href="profile\.php\?id=[0-9]+">.*?<\/a><\/td>/g);
    const parseData = new DOMParser();
    const bodyHtml = parseData.parseFromString(document.body.innerHTML, 'text/html');
    const nativeMemberTable = bodyHtml.querySelector('.table.table-bordered.table-striped').innerHTML;
    const nativeDetails = bodyHtml.querySelector('.row div ul').parentNode.parentNode.outerHTML;
    const breakAlliance = document.body.innerHTML.match(/id=[0-9]+&amp;ally=2/i)
    const formAlliance = document.body.innerHTML.match(/id=[0-9]+&amp;ally=1/i)
    const dropdownOptions = bodyHtml.querySelector("#content-header-row > div:nth-child(2) > div > div.btn-group.mb-3.mr-2");
    const treasuryLink = document.body.innerHTML.match(/<a href="(\/treasury\?search_for=.*?)">/i)[1]
    const crewId = document.body.innerHTML.match(/<a href="crew_raidresults\.php\?crewid=([0-9]+)&amp;most_recent=1">/i)[1]

    const myCrewButtons = `
    <div class="btn-group show" role="group">
    <button type="button" class="btn-mm dropdown-toggle" data-toggle="dropdown">CREW PAGES <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg></button>
    <div id="crewActionsDropdown" class="dropdown-menu" style="will-change: transform; position: absolute; transform: translate3d(0px, 38px, 0px); top: 0px; left: 0px;">
    <a class="dropdown-item" href="trade?isCrewTrade=1&amp;tradeWith=${crewId}">Trade with ${crewName}</a>
    <a class="dropdown-item" href="${treasuryLink}">${crewName} Treasury</a>
    <a class="dropdown-item" href="crew_raidresults.php?crewid=${crewId}&moxximod">Raid Results</a>
    <a class="dropdown-item" href="javascript:void(0);" id="showCrewUpgrades">Crew Upgrades</a>
    <a class="dropdown-item" href="javascript:void(0);" id="showCrewAllies">Crew Allies</a>
    </div>
    </div>`


    document.querySelector("#content").innerHTML = `

    <div class="widget-content widget-content-area">
    <div class="bio-skill-box">
    <div class="row">

    <div class="col-12 col-xl-5">
    <h3>${crewName}</h3><hr>
    ${nativeDetails}<hr>
    <div>

    <div class="button-container">
    <div class="btn-group show" role="group">
    <button type="button" class="btn-mm dropdown-toggle" data-toggle="dropdown">MEMBER DETAILS <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg></button>
    <div class="dropdown-menu" style="will-change: transform; position: absolute; transform: translate3d(0px, 38px, 0px); top: 0px; left: 0px;">
    <a class="dropdown-item" href="javascript:void(0);" id="mbr-stats">STATISTICS</a>
    <a class="dropdown-item" href="javascript:void(0);" id="mbr-items">ITEMS</a>
    <a class="dropdown-item" href="javascript:void(0);" id="mbr-skills">SKILLS</a>
    </div>
    </div>
    </div>

    <div class="button-container">
    ${myCrewButtons}
    </div>

    <hr>
    <div id="actionSpace"></div>
    </div>
    </div>

    <div class="col-12 col-xl-4">
    <img src="${crewPic}" class="crew-profile-pic">
    </div>

    <div class="col-12 col-xl-3">
    <div id="nativeMemberTable">
    <table class="table table-striped">
    ${nativeMemberTable.replace(/<th>Level<\/th>/i,'').replace(/<td>\b\d{1,3}\b<\/td>/g,'')}
    </table>
    </div>
    </div>

    </div>
    </div>
    </div>

    <div id="crewMemberDiv" class="widget-content widget-content-area" style="border-radius:0px;top:-5px;">
    <div id="crewMemberTable"></div>
    </div>

    `


    var crewActionsDropdown = document.getElementById("crewActionsDropdown");
    if (dropdownOptions){
        if (dropdownOptions.innerHTML.match(/href="\/crew_invites"/)) {
            crewActionsDropdown.innerHTML += `<a class="dropdown-item" href="crew_invites">Send Crew Invites</a>`;
        }
        if (dropdownOptions.innerHTML.match(/href="\/crew_image"/)) {
            crewActionsDropdown.innerHTML += `<a class="dropdown-item" href="crew_image">Edit Crew Picture</a>`;
        }
        if (dropdownOptions.innerHTML.match(/href="\/crew_changerank"/)) {
            crewActionsDropdown.innerHTML += `<a class="dropdown-item" href="crew_changerank">Change Ranks</a>`;
        }
        if (dropdownOptions.innerHTML.match(/href="\/crew_ranknames"/)) {
            crewActionsDropdown.innerHTML += `<a class="dropdown-item" href="crew_ranknames">Change Rank Names</a>`;
        }
        if (dropdownOptions.innerHTML.match(/href="\/crew_bootmem"/)) {
            crewActionsDropdown.innerHTML += `<a class="dropdown-item" href="crew_bootmem">Boot Members</a>`;
        }
        if (dropdownOptions.innerHTML.match(/href="\/crew_actionlog"/)) {
            crewActionsDropdown.innerHTML += `<a class="dropdown-item" href="crew_actionlog">Crew Action Log</a>`;
        }
        if (dropdownOptions.innerHTML.match(/href="\/crew_vault"/)) {
            crewActionsDropdown.innerHTML += `<a class="dropdown-item" href="crew_vault">Vault & Storage</a>`;
        }
        if (dropdownOptions.innerHTML.match(/href="\/crew_capstatus"/)) {
            crewActionsDropdown.innerHTML += `<a class="dropdown-item" href="crew_capstatus">Character Cap Status</a>`;
        }
        if (dropdownOptions.innerHTML.match(/href="\/crew_adminpanel"/)) {
            crewActionsDropdown.innerHTML += `<a class="dropdown-item" href="crew_adminpanel">Admin Panel</a>`;
        }
    };

    if (formAlliance){
        var a = document.createElement("a");
        a.className = "dropdown-item";
        a.setAttribute('style','cursor:pointer;')
        a.addEventListener('click', function(){
            window.location.href = `crew_profile.php?${formAlliance.toString().replace('amp;','')}`
            alert('You are now allied to this crew');
            window.location.href = window.location.href.replace(/&ally=[0-9]+/i,'');
        })
        a.textContent = "Form Alliance";
        crewActionsDropdown.appendChild(a);
    };
    if (breakAlliance){
        var a = document.createElement("a");
        a.className = "dropdown-item";
        a.setAttribute('style','cursor:pointer;')
        a.addEventListener('click', function(){
            window.location.href = `crew_profile.php?${breakAlliance.toString().replace('amp;','')}`
            alert('You are no longer allied to this crew');
            window.location.href = window.location.href.replace(/&ally=[0-9]+/i,'');
        })
        a.textContent = "Break Alliance";
        crewActionsDropdown.appendChild(a);
    };

    document.querySelector("#mbr-stats").addEventListener('click',memberStats)
    document.querySelector("#mbr-items").addEventListener('click',memberItems)
    document.querySelector("#mbr-skills").addEventListener('click',memberSkills)

    async function memberStats(){

        document.querySelector("#actionSpace").innerHTML = `<div><img src="https://studiomoxxi.com/moxximod/loading-gif.gif" style="height:100px;width:100px;padding:20px"></div>`

        const memberData = []
        let count = 0
        const buildTable = async (item) => {
            count++
            const position = count;
            const charId = item.match(/<a href="profile\.php\?id=([0-9]+)">/i)[1];
            const profile = await superfetch(`profile?id=${charId}`);
            const name = `<a href='profile.php?id=${charId}'>${profile.match(/<font size="3">(.*?)<\/font>/i)[1]}</a>`;
            const level = profile.match(/<font size="2">Level ([0-9]+) .*?<\/font>/i)[1];
            const power = parseInt(profile.replace(/,/g,'').match(/TOTAL POWER<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]).toLocaleString();
            const ele = parseInt(profile.replace(/,/g,'').match(/ELEMENTAL ATTACK<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]).toLocaleString();
            const slayer = parseInt(profile.replace(/,/g,'').match(/GOD SLAYER LEVEL<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]).toLocaleString();
            const wldr = parseInt(profile.replace(/,/g,'').match(/WILDERNESS LEVEL<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]).toLocaleString();
            const chaos = parseInt(profile.replace(/,/g,'').match(/CHAOS DAMAGE<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]).toLocaleString();
            const atk = parseInt(profile.replace(/,/g,'').match(/ATTACK<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]).toLocaleString();
            const hp = parseInt(profile.replace(/,/g,'').match(/HIT POINTS<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]).toLocaleString();
            const growth = parseInt(profile.replace(/,/g,'').match(/GROWTH YESTERDAY<\/font><\/b><\/td>[\n\r].*?<font size="2">(.*?)<\/font>/i)[1]).toLocaleString();
            const resistance = parseInt(profile.replace(/,/g,'').match(/ELEMENTAL RESIST<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]).toLocaleString();
            const factionMatch = profile.match(/<font size="1">FACTION<\/font><\/b><\/td>\n.*?([A-Za-z]+) \((.*?)\)/i)
            const faction = factionMatch[1]
            const loyalty = factionMatch[2] === "" ? '0' : factionMatch[2];
            memberData.push({ position,name,level,power,ele,chaos,faction,loyalty,slayer,wldr,atk,hp,resistance,growth });
        };
        await Promise.all(crewMembers.map(buildTable));

        memberData.sort((a, b) => a.position - b.position);

        const memberDataWithoutPosition = memberData.map(({ position, ...rest }) => rest);
        const allRows = [];
        memberDataWithoutPosition.forEach(char => {
            const row = [];
            Object.keys(char).forEach(td => {
                row.push(`<td>${char[td]}</td>`);
            });
            allRows.push(`<tr>${row.join('')}</tr>`);
        });
        document.querySelector("#crewMemberTable").innerHTML = `
            <table id="crewMemberTable" class="table sortable">
            <thead><th>name</th><th>level</th><th>power</th><th>ele</th><th>chaos</th><th>faction</th><th>loyalty</th><th>slayer</th><th>wldr</th><th>atk</th><th>hp</th><th>resistance</th><th>growth</th></thead>
            <tbody>${allRows.join('')}</tbody>
            </table>
        `

        let totalPower = 0; let totalEle = 0; let totalChaos = 0; let totalLoyalty = 0; let totalSlayer = 0; let totalWldr = 0; let totalRes = 0; let totalGrowth = 0; let totalAtk = 0; let totalHp = 0
        memberDataWithoutPosition.forEach(function(obj) {
            Object.entries(obj).forEach(function([key, value]) {
                var cell = document.createElement("td");
                cell.innerHTML = value;
                if (value.match(/<a href='profile\.php\?id=[0-9]+'>.*?<\/a>/i)){
                    cell.setAttribute('style',`position: sticky;left:0px;`);
                };
                if (key == "power"){ totalPower += parseInt(value.replace(/,/g,'')) };
                if (key == "ele"){ totalEle += parseInt(value.replace(/,/g,'')) };
                if (key == "chaos"){ totalChaos += parseInt(value.replace(/,/g,'')) };
                if (key == "loyalty"){ totalLoyalty += parseInt(value.replace(/,/g,'')) };
                if (key == "wldr"){ totalWldr += parseInt(value.replace(/,/g,'')) };
                if (key == "slayer"){ totalSlayer += parseInt(value.replace(/,/g,'')) };
                if (key == "resistance"){ totalRes += parseInt(value.replace(/,/g,'')) };
                if (key == "growth"){ totalGrowth += parseInt(value.replace(/,/g,'')) };
                if (key == "atk"){ totalAtk += parseInt(value.replace(/,/g,'')) };
                if (key == "hp"){ totalHp += parseInt(value.replace(/,/g,'')) };
            });
        });

        GM_addStyle(`#crewMemberDiv{overflow:hidden;display:block;}`);

        document.querySelector("#actionSpace").innerHTML = `
        <div class="row">
        <div class="col-6 pr-1">
        <ul class="list-group text-left">
        <li class="list-group-item"><b>Total Power:</b> ${totalPower.toLocaleString()}</li>
        <li class="list-group-item"><b>Total Elemental:</b> ${totalEle.toLocaleString()}</li>
        <li class="list-group-item"><b>Total Resistance:</b> ${totalRes.toLocaleString()}</li>
        <li class="list-group-item"><b>Total God Slayer:</b> ${totalSlayer.toLocaleString()}</li>
        <li class="list-group-item"><b>Total Growth:</b> ${totalGrowth.toLocaleString()}</li>
        </ul>
        </div>
        <div class="col-6 pl-1">
        <ul class="list-group text-left">
        <li class="list-group-item"><b>Total Chaos Damage:</b> ${totalChaos.toLocaleString()}</li>
        <li class="list-group-item"><b>Total Faction Loyalty:</b> ${totalLoyalty.toLocaleString()}</li>
        <li class="list-group-item"><b>Total Wilderness:</b> ${totalWldr.toLocaleString()}</li>
        <li class="list-group-item"><b>Total Attack:</b> ${totalAtk.toLocaleString()}</li>
        <li class="list-group-item"><b>Total Hit Points:</b> ${totalHp.toLocaleString()}</li>
        </ul>
        </div>
        </div>
        `

        await sortableTables();
    };

    async function memberItems(){

        document.querySelector("#actionSpace").innerHTML = `<div><img src="https://studiomoxxi.com/moxximod/loading-gif.gif" style="height:100px;width:100px;padding:20px"></div>`

        const memberData = []
        let count = 0
        const buildTable = async (item) => {
            count++
            const position = count;
            const charId = item.match(/<a href="profile\.php\?id=([0-9]+)">/i)[1];
            const profile = await superfetch(`profile?id=${charId}`);
            const name = `<a href='profile.php?id=${charId}'>${profile.match(/<font size="3">(.*?)<\/font>/i)[1]}</a>`;
            const core = profile.match(/left:61px; top:12px; width:41px; height:41px;text-align:center">[\n\r](<.*?>)/i)[1]
            const head = profile.match(/left:118px; top:7px; width:62px; height:46px;text-align:center">[\n\r](<.*?>)/i)[1]
            const neck = profile.match(/left:197px; top:12px; width:41px; height:41px;text-align:center">[\n\r](<.*?>)/i)[1]
            const wepn = profile.match(/left:45px; top:67px; width:56px; height:96px;text-align:center">[\n\r](<.*?>)/i)[1]
            const body = profile.match(/left:121px; top:67px; width:56px; height:96px;text-align:center">[\n\r](<.*?>)/i)[1]
            const shld = profile.match(/left:198px; top:67px; width:56px; height:96px;text-align:center">[\n\r](<.*?>)/i)[1]
            const belt = profile.match(/left:61px; top:192px; width:41px; height:41px;text-align:center">[\n\r](<.*?>)/i)[1]
            const pant = profile.match(/left:118px; top:175px; width:62px; height:75px;text-align:center">[\n\r](<.*?>)/i)[1]
            const ring = profile.match(/left:197px; top:192px; width:41px; height:41px;text-align:center">[\n\r](<.*?>)/i)[1]
            const foot = profile.match(/left:118px; top:262px; width:62px; height:66px;text-align:center">[\n\r](<.*?>)/i)[1]
            const cgem = profile.match(/left:10px; top:346px; width:32px; height:32px;text-align:center">[\n\r](<.*?>)/i)[1]
            const bdge = profile.match(/left:214px; top:346px; width:32px; height:32px;text-align:center">[\n\r](<.*?>)/i)[1]
            const rune = profile.match(/left:54px; top:346px; width:32px; height:32px;text-align:center">[\n\r](<.*?>)/i)[1]
            const bstr = profile.match(/left:258px; top:346px; width:32px; height:32px;text-align:center">[\n\r](<.*?>)/i)[1]
            const orbs = profile.match(/left:100px; top:346px; width:99px; height:32px;text-align:center">[\s\S](.*?)<\/div>/i)[1]
            const orbMatches = orbs.match(/<img style="border:0px;" src="[^"]*" onclick="window\.location='[^']*'" ONMOUSEOVER="itempopup\(event,'[0-9]+'\)" ONMOUSEOUT="kill\(\)" alt="[^"]*">/g) || [];
            const orbsArray = Array.from({ length: 3 }, (_, index) => orbMatches[index] || '');
            const [orb1, orb2, orb3] = orbsArray;
            memberData.push({ position,name,core,head,neck,wepn,body,shld,belt,pant,ring,foot,orb1,orb2,orb3,cgem,bdge,rune,bstr });
        };
        await Promise.all(crewMembers.map(buildTable));

        memberData.sort((a, b) => a.position - b.position);

        const memberDataWithoutPosition = memberData.map(({ position, ...rest }) => rest);
        const allRows = [];
        memberDataWithoutPosition.forEach(char => {
            const row = [];
            Object.keys(char).forEach(td => {
                row.push(`<td>${char[td]}</td>`);
            });
            allRows.push(`<tr>${row.join('')}</tr>`);
        });
        document.querySelector("#crewMemberTable").innerHTML = `
            <table id="crewMemberTable" class="table">
            <tbody>${allRows.join('')}</tbody>
            </table>
        `

        GM_addStyle(`#crewMemberDiv{overflow:hidden;display:block;}`);

        document.querySelector("#actionSpace").innerHTML = ''
    };

    async function memberSkills(){

        document.querySelector("#actionSpace").innerHTML = `<div><img src="https://studiomoxxi.com/moxximod/loading-gif.gif" style="height:100px;width:100px;padding:20px"></div>`

        const memberData = []
        let count = 0
        const buildTable = async (item) => {
            count++
            const position = count;
            const charId = item.match(/<a href="profile\.php\?id=([0-9]+)">/i)[1];
            const profile = await superfetch(`profile?id=${charId}`);
            const parseData = new DOMParser();
            const profileHtml = parseData.parseFromString(profile, 'text/html');
            const skills = profileHtml.querySelector("#divSkillsCast").innerHTML.replace(/<img src=".*?ProfileSkills\.png">/i,'')
            const name = `<a href='profile.php?id=${charId}'>${profile.match(/<font size="3">(.*?)<\/font>/i)[1]}</a>`;
            memberData.push({ position,name,skills });
        };
        await Promise.all(crewMembers.map(buildTable));

        memberData.sort((a, b) => a.position - b.position);

        const memberDataWithoutPosition = memberData.map(({ position, ...rest }) => rest);
        const allRows = [];
        memberDataWithoutPosition.forEach(char => {
            const row = [];
            Object.keys(char).forEach(td => {
                row.push(`<td>${char[td]}</td>`);
            });
            allRows.push(`<tr>${row.join('')}</tr>`);
        });
        document.querySelector("#crewMemberTable").innerHTML = `
            <table id="crewMemberTable" class="table">
            <tbody>${allRows.join('')}</tbody>
            </table>
        `

        GM_addStyle(`#crewMemberDiv{overflow:hidden;display:block;}`);

        document.querySelector("#actionSpace").innerHTML = ''
    };


    document.querySelector("#showCrewUpgrades").addEventListener('click',function(){
        document.querySelector("#actionSpace").innerHTML = `${crewUpgrades.join(' ')}<br>${crewStones.join(' ')}`
    });

    document.querySelector("#showCrewAllies").addEventListener('click',function(){
        document.querySelector("#actionSpace").innerHTML = crewAllies
    });
};


async function augmentEquip(server){

    document.querySelector("#content-header-row > div > div:nth-child(1)").setAttribute('style','display:none;');

    document.querySelector("#content-header-row > div > div:nth-child(2)").classList.add("widget");

    document.body.setAttribute('style','overflow-y:scroll;')

    const addAugText = document.querySelector("#content-header-row > div > div:nth-child(2) > div:nth-child(2) > div:nth-child(2)")
    addAugText.innerHTML = addAugText.innerHTML.replace(/You have no augments in this category/g,'')
    var augChange = document.querySelector("#item-container")
    const addAugWidget = document.querySelector("#content-header-row > div > div.row.widget > div:nth-child(2) > div:nth-child(1)")
    let observer = new MutationObserver(mutationRecords => { addAug(); });
    observer.observe(augChange, {
      childList: true,
      subtree: true,
      characterDataOldValue: true
    });
    function addAug(){

        const selectedAug = document.querySelector("#item-container > div:nth-child(4) > div > img")
        if (document.querySelector("#item-container").innerHTML.match(/src="\/images\/augslot\.jpg"><h5>Slot ([0-9]+)<\/h5>/i) && selectedAug){
            var openAug = document.querySelector("#item-container").innerHTML.match(/src="\/images\/augslot\.jpg"><h5>Slot ([0-9]+)<\/h5>/i)[1]
            document.querySelector("#form-slotid").value = openAug;
        };

        if (addAugWidget){
            if (GM_getValue("savedAug")){
                const savedAugImg = GM_getValue("savedAug")
                document.querySelector("#augName").value = savedAugImg
                if (document.querySelector('img[src="http://'+server+'.outwar.com/' + savedAugImg + '"]')){
                    document.querySelector('img[src="http://'+server+'.outwar.com/' + savedAugImg + '"]').click();
                };
            };
        };

        if (addAugWidget && !document.querySelector("#saveAugType") && document.querySelector("#item-container > div:nth-child(4) > div > img")){
            const newDivElement = document.createElement("div");
            newDivElement.setAttribute('id','saveAugType');
            newDivElement.setAttribute('class','col-inner');
            newDivElement.setAttribute('style','padding:10px;');
            newDivElement.innerHTML = `<button id="saveAugName" class="btn btn-primary" style="margin-rght:15px;">Auto Select This Aug</button><button id="clearAugName" class="btn btn-primary" style="margin-left:15px;">Clear Save</button><p>`
            addAugWidget.appendChild(newDivElement);
            document.querySelector("#saveAugName").addEventListener("click", function(){
                const augNameInput = document.querySelector("#augName").value
                GM_setValue("savedAug", augNameInput);
                alert('Will auto-select this augment when adding augs')
            });
            document.querySelector("#clearAugName").addEventListener("click", function(){
                GM.deleteValue("savedAug")
                alert('Saved augment has been cleared')
            });
        }

        const augsDiv = document.querySelector("#content-header-row > div > div:nth-child(2) > div:nth-child(2) > div:nth-child(2)").innerHTML
        if (augsDiv.match(/style="border: 2px solid rgb\(204, 0, 0\);"><img border="0" width="20" height="20" src=".*?(images\/.*?)"/i)){
            const selectedAug = augsDiv.match(/style="border: 2px solid rgb\(204, 0, 0\);"><img border="0" width="20" height="20" src=".*?(images\/.*?)"/i)[1]
            document.querySelector("#augName").value = selectedAug
        };
    };

    const targetElement = document.querySelector("#content-header-row > div > div.row.widget > div:nth-child(2)");
    const newDivElement = document.createElement("div");
    newDivElement.innerHTML = `<input type="text" id="augName" class="form-control" size="10" autocomplete="off" style="width:300px;height:38px;display:none;font-size:11px;">`
    targetElement.appendChild(newDivElement);
};


async function trade(){

    if (document.body.innerHTML.match('This trade has been completed!') || document.URL.match("usertradelog") || document.URL.match("tradepost")){
        return;
    };

    GM_addStyle(`
    #divTrade > div > div > img {min-width:50px;min-height:50px;margin-bottom:7px;}
    #divTrade > div > div > p {position:relative;top:0px;height:15px;width:50px;left:0px;font-size:10px !important;border: SOLID 1px #2B2B2B;}
    button.btn-mm{font-size:11px;padding:0.5rem;}
    #otherGuy > a{color:#00CC00;}
    #otherGuy > a:hover{color:#FFFFFF;}
    `);

    const myaccount = await superfetch('myaccount');

    const slotDiv = document.querySelectorAll("#divTrade > div")
    const removeNoItems = async (div) => {
        if (div.innerHTML.toString().match('You have no items in this category')){
            div.remove();
        };
    };
    await Promise.all([...slotDiv].map(removeNoItems));

    const slotHeader = document.querySelectorAll("#divTrade > div > h1")
    const removeHeaders = async (header) => {
        header.remove();
    };
    await Promise.all([...slotHeader].map(removeHeaders));

    const quantityP = document.querySelectorAll("#divTrade > div > div > p")
    const formatQuantity = async (qnt) => {
        qnt.setAttribute('class','form-control-new')
    };
    await Promise.all([...quantityP].map(formatQuantity));

    const myOffer = document.querySelector("#divTradeMyOffer");
    const theirOffer = document.querySelector("#divTradeTheirOffer");
    if (myOffer && theirOffer){
        myOffer.classList.remove('col-lg-6')
        theirOffer.classList.remove('col-lg-6')
        myOffer.classList.add('col-lg-5')
        theirOffer.classList.add('col-lg-5')
    };

    var parentDiv = document.querySelector("#divTradeData")
    var newDiv = document.createElement("div");
    newDiv.className = "col-12 col-lg-2";
    newDiv.setAttribute('style','padding:19px;display:inline-block;overflow:hidden;')
    newDiv.innerHTML = `
    <strong>Options</strong>
    <div class="divBlackBox statbox widget box box-shadow" style="border: 4px solid #2B2B2B;">
    Default Qnty<input style="width:120px;" id="defQnty" type="text" class="form-control-new" autocomplete="off"><br>
    <button class="btn-mm" id="saveDefQnty" style="margin-top:10px;">SAVE</button>
    <hr>
    <div class="btn-group show" role="group">
    <button type="button" class="btn-mm dropdown-toggle" data-toggle="dropdown">SELECT <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg></button>
    <div class="dropdown-menu" style="will-change: transform; position: absolute; transform: translate3d(0px, 38px, 0px); top: 0px; left: 0px;">
    <a class="dropdown-item select-all" id="all" href="javascript:void(0);">ALL ITEMS</a>
    <a class="dropdown-item select-all" id="blackhand" href="javascript:void(0);">BLACKHAND ITEMS</a>
    </div>
    </div>
    </div>`

    if (document.body.innerHTML.match('You have accepted this trade')){
        const parseData = new DOMParser();
        const myAccount = parseData.parseFromString(myaccount, 'text/html');
        const charsTable = myAccount.querySelector("#zero-config").innerHTML;
        const otherName = document.body.innerHTML.match(/([A-Za-z0-9]+)'s Offer/i)[1]
        const otherId = document.body.innerHTML.match(/name="tradeWith" value="([0-9]+)"/i)[1]
        const idMatch = new RegExp(`outwar\\.com\/world\\?suid=${otherId}`);
        if (charsTable.match(idMatch)){
            document.querySelector("#divTradeMyOffer > div:nth-child(4)").innerHTML = `
            <div id="otherGuy">
            <a href="trade?suid=${otherId}">Go to ${otherName}</a>
            </div>
            `
        };
    };

    const lists = {
        blackhand: ['Soul of Blackhand Reborn','Myrmidon Helm Reborn','Trinket of Aridity Reborn','Blackhand Reborn','Prophecy Mail Reborn','Incredible Tower Shield Reborn','Cord of Freezing Winds Reborn','Interstellar Leggings Reborn','Ring of the Sea Reborn','Boots of the Eagle Reborn'],
    };

    const divItem = document.querySelectorAll(".divItem");

    for (let i = 0; i < divItem.length; i++) {

        const itemName = divItem[i].outerHTML.match(/alt="([^"]*)"/i)[1];

        if (!itemName.match('Amulet Chest')){
            divItem[i].classList.add("all");
        };

        for (const key in lists){
            if (lists[key].includes(itemName)){

                divItem[i].classList.add(key);
            };
        };

        divItem[i].addEventListener("click", async function() {

            const maxItems = parseInt(divItem[i].outerHTML.match(/event, '[^']*', '[^']*', '[^']*', '([0-9]+)'/i)[1]);

            if (maxItems > 1){

                let setValue = GM_getValue("tradeQuantity")
                if (setValue > maxItems){
                    setValue = maxItems;
                };

                if (GM_getValue("tradeQuantity")){
                    document.querySelector("#cauldronqtyspinner").value = setValue;
                };
            };
        });
    };


    var child = parentDiv.firstElementChild.nextElementSibling;
    parentDiv.insertBefore(newDiv, child);

    const selectAllButtons = document.querySelectorAll(".select-all");
    for (let i = 0; i < selectAllButtons.length; i++) {
        var button = selectAllButtons[i];
        const buttonId = button.id

        button.addEventListener("click", async function() {

            const items = document.querySelectorAll(`.${buttonId}`)

            const selectAll = async (item) => {

                const maxItems = parseInt(item.outerHTML.match(/event, '[^']*', '[^']*', '[^']*', '([0-9]+)'/i)[1]);
                const tradeWith = document.body.innerHTML.match(/name="tradeWith" value="([0-9]+)"/i)[1]
                const isCrewTrade = document.body.innerHTML.match(/id="isCrewTrade" value="([0-9]+)"/i)[1]
                const itemId = item.outerHTML.match(/event, '([^']*)', '[^']*', '[^']*'/i)[1];
                const itemHash = item.outerHTML.match(/event, '[^']*', '[^']*', '([^']*)'/i)[1];

                const response = await fetch(`trade.php?tradeWith=${tradeWith}&isCrewTrade=${isCrewTrade}&qty=${maxItems}&addItem=${itemId}&addHash=${itemHash}`, {
                    method: 'GET',
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
                });
                if (response){
                    window.location.href =  `trade?isCrewTrade=${isCrewTrade}`
                };
            };
            await Promise.all([...items].map(selectAll));
        });
    };


    const quantityText = document.querySelector("#defQnty")
    if (GM_getValue('tradeQuantity')){
        quantityText.value = GM_getValue('tradeQuantity');
    };
    document.querySelector("#saveDefQnty").addEventListener('click', async function(){
        const defaultQuantityValue = quantityText.value
        GM_setValue('tradeQuantity',defaultQuantityValue);
    });
};


async function closedpvp(profile,server,charid){
    GM_addStyle(`
    #content-header-row > div:nth-child(3) > div{height:100%}
    #content-header-row > div:nth-child(2) > div.widget-content.widget-content-area.mt-3 > img{height:25px;width:25px;margin:4px;border-radius:5px;}
    #content-header-row > div:nth-child(2) > div:nth-child(1) > div{left:25px;}
    `)

    if (document.body.innerHTML.match('BRAWL IS ACTIVE') && document.body.innerHTML.match('You are entered into the brawl')){

        const playerRows = document.querySelectorAll("#content-header-row > div:nth-child(4) > div > table > tbody > tr");

        document.querySelector("#content-header-row > div:nth-child(3) > div:nth-child(2)").remove();
        document.querySelector("#content-header-row > div:nth-child(3) > div.widget-content.widget-content-area.mt-3").remove();
        document.querySelector("#content-header-row > h2").remove();
        document.querySelector("#content-header-row > div:nth-child(2) > div > ul").remove();
        document.querySelector("#content-header-row > div:nth-child(2) > div > p").remove();
        document.querySelector("#content-header-row > div:nth-child(2) > div > h4").remove();
        if (document.querySelector("#content-header-row > div:nth-child(2) > div > h3")){
            document.querySelector("#content-header-row > div:nth-child(2) > div > h3").remove();
        };

        const allCast = profile.match(/<img align="absmiddle" border="0" src="[^"]*" hspace="2" width="25" height="25" alt="[^"]*" ONMOUSEOVER="popup\(event,'[^']*',[0-9]+\)" ONMOUSEOUT="kill\(\)">/g) || [];
        const yourName = profile.match(/<font size="3">(.*?)<\/font>/i)[1]
        const yourPower = parseInt(profile.replace(/,/g,'').match(/TOTAL POWER<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]);
        document.querySelector("#content-header-row > div:nth-child(2) > div.widget-content.widget-content-area.mt-3").innerHTML = `
        <h5>Your Power</h5>
        ${yourPower.toLocaleString()}<hr>
        <h5>Your skills</h5>
        ${allCast.join(' ')}<hr>
        <button class="btn-mm" id="hideAttacked" style="margin-bottom:10px;">HIDE ATTACKED PLAYERS</button>
        <button class="btn-mm" id="showAll" style="margin-bottom:10px;">SHOW ALL PLAYERS</button>
        `
        document.querySelector("#content-header-row > div:nth-child(3)").innerHTML = `
        <div class="widget-content widget-content-area">
        <img src="https://studiomoxxi.com/moxximod/bot.png">
        <hr>
        <h5> Sunder armor</h5>
        <input style="width:135px;" id="saTarget1" type="text" class="form-control-new" autocomplete="off">
        <input style="width:135px;" id="saTarget2" type="text" class="form-control-new" autocomplete="off">
        <input style="width:135px;" id="saTarget3" type="text" class="form-control-new" autocomplete="off"><br>
        <button class="btn-mm" id="castSunderArmor" style="margin-top:10px;">CAST SUNDER ARMOR</button><hr>
        <h5 style="margin-top:1rem;">Poison dart</h5>
        <input style="width:135px;" id="pdTarget" type="text" class="form-control-new" autocomplete="off"><br>
        <button class="btn-mm" id="castPoisonDart" style="margin-top:10px;">CAST POISON DART</button>
        </div>
        `
        let saCharging;
        let pdCharging;
        const sunderArmor = await superfetch('skills_info.php?id=21');
        const saCooldown = sunderArmor.match(/This skill is recharging\. [0-9]+ minutes remaining\./i);
        const saUnknown = sunderArmor.match(/You have not learned this skill yet/i);
        if (saCooldown || saUnknown){
            document.querySelector("#castSunderArmor").outerHTML = `<br>Sunder armor isn't available to cast`
            saCharging = true;
        }
        const poisonDart = await superfetch('skills_info.php?id=16');
        const pdCooldown = poisonDart.match(/This skill is recharging\. [0-9]+ minutes remaining\./i);
        const pdUnknown = poisonDart.match(/You have not learned this skill yet/i);
        if (pdCooldown || pdUnknown){
            document.querySelector("#castPoisonDart").outerHTML = `<br>Poison dart isn't available to cast`
            pdCharging = true;
        }

        var parentElement = document.querySelector("#content > div.layout-px-spacing");

        var newDiv = document.createElement("div");
        newDiv.innerHTML = `
        <table id="brawlTable" class="table table-striped">
        <thead><tr><th>Rank</th><th>Player</th><th>Prize</th><th>Power</th><th>Wins</th><th>Damage</th><th>Skills</th><th>Atks</th><th>Attack</th><th>Wait</th></thead>
        <tbody></tbody>
        </table>`;
        newDiv.setAttribute('class','row justify-content-center widget-content widget-content-area');
        newDiv.setAttribute('style','margin-top:1rem;margin-left:2px;margin-right:2px;');
        parentElement.appendChild(newDiv);

        let data = [];
        const buildTable = async (item,index) => {
            const row = item.innerHTML.replace(/,/g,'');
            const brawlPlayerid = row.match(/id=([0-9]+)/i)[1];
            const profile = await superfetch(`profile?id=${brawlPlayerid}`);
            const brawlRank = parseInt(row.match(/<td>([0-9]+)\.<\/td>/i)[1]);
            let brawlPrize = '';
            if (brawlRank == 1){ brawlPrize = '20 coins'}
            else if (brawlRank == 2){ brawlPrize = '17 coins'}
            else if (brawlRank == 3){ brawlPrize = '15 coins'}
            else if (brawlRank == 4){ brawlPrize = '13 coins'}
            else if (brawlRank == 5){ brawlPrize = '11 coins'}
            else if (brawlRank <= 8){ brawlPrize = '10 coins'}
            else if (brawlRank <= 11){ brawlPrize = '9 coins'}
            else if (brawlRank <= 14){ brawlPrize = '8 coins'}
            else if (brawlRank <= 17){ brawlPrize = '7 coins'}
            else if (brawlRank <= 20){ brawlPrize = '6 coins'}
            else if (brawlRank <= 25){ brawlPrize = '5 coins'}
            else if (brawlRank <= 30){ brawlPrize = '4 coins'}
            const brawlPlayer = row.match(/<a href="profile\?id=[0-9]+">(.*?)<\/a>/i)[1];
            const parsePower = parseInt(profile.replace(/,/g,'').match(/TOTAL POWER<\/font><\/b><\/td>[\n\r].*?<font size="2">([0-9]+)<\/font>/i)[1]);
            let brawlPlayerpower;
                if (Math.abs(yourPower-parsePower) <= (yourPower*0.0375)){brawlPlayerpower = `<font color="#ffea00">${parsePower.toLocaleString()}</font>`}
                else if ((parsePower-yourPower) >= (yourPower*0.0375)){brawlPlayerpower = `<font color="#d40000">${parsePower.toLocaleString()}</font>`}
                else if ((yourPower-parsePower) >= (yourPower*0.0375)){brawlPlayerpower = `<font color="#00dc24">${parsePower.toLocaleString()}</font>`};
            const brawlWins = row.match(/([0-9]+)<\/td>[\n\r]<td>[\n\r][0-9]+<\/td>/i)[1];
            const brawlDamage = parseInt(row.match(/[0-9]+<\/td>[\n\r]<td>[\n\r]([0-9]+)<\/td>/i)[1]).toLocaleString();
            const brawlYourattacks = row.match(/[0-9]+<\/td>[\n\r]<td>(.*?)<\/td>/i) ? row.match(/[0-9]+<\/td>[\n\r]<td>(.*?)<\/td>/i)[1] : row.match(/[0-9]+<\/td>[\n\r]<td>([0-9]+) <a href/i)[1];
            const brawlCop = profile.match(/alt="Circle of Protection"/i) ? `<font color="#ffea00">Circle of Protection: ${profile.match(/alt="Circle of Protection".*<br \/>(.*?) left/i)[1]}</font>` : '';
            const brawlCopstring = brawlCop.match(/: .*?</i) ? `${brawlCop.match(/: .*?</i).toString().replace(/:\s*|\s+|min|</gi, '').replace(/s/g,'')}` : ''
            let brawlSkills = [];
                const sunderCast = new RegExp("Sunder Armor<\/b><br \/>Target takes 30% more damage from you\. Only castable if you have no active Sunder debuffs cast\.<br \/>(.*)<br>Cast By "+yourName,"i")
                const dartCast = new RegExp("Poison Dart<\/b><br \/>You strike your target with a poisonous dart\. Target takes 5,000 damage each time they attack you, or you attack them\.<br \/>(.*)<br>Cast By "+yourName,"i")
                const sunderHit = new RegExp("Sunder Armor<\/b><br \/>Target takes 30% more damage from you\. Only castable if you have no active Sunder debuffs cast\.<br \/>(.*)<br>Cast By "+brawlPlayer,"i")
                const dartHit = new RegExp("Poison Dart<\/b><br \/>You strike your target with a poisonous dart\. Target takes 5,000 damage each time they attack you, or you attack them\.<br \/>(.*)<br>Cast By "+brawlPlayer,"i")
                if (brawlCop != ''){ brawlSkills.push(brawlCop) };
                if (profile.match(sunderCast)){ brawlSkills.push('<font color="#00dc24">You cast Sunder Armor</font>') };
                if (profile.match(dartCast)){ brawlSkills.push('<font color="#00dc24">You cast Poison Dart</font>') };
                if (allCast.join('\n').match(sunderHit)){ brawlSkills.push('<font color="#d40000">Cast Sunder Armor on you</font>') }
                if (allCast.join('\n').match(dartHit)){brawlSkills.push('<font color="#d40000">Cast Poison Dart on you</font>') }
            const brawlAttackbtn = brawlYourattacks.match('10') || brawlYourattacks.match('-') ? '' : `<button class="btn-mm attack-10x" id="" alt="${brawlPlayerid}">ATTACK 10X</button>`;
            const brawlWaitforcop = brawlYourattacks.match('10') || brawlCop == '' ? '' : `<button class="btn-mm wait-for-cop" alt="${brawlPlayerid}|${brawlCopstring}">WAIT FOR COP</button>`;
            data.push(rowData = {
                rank: brawlRank,
                player: `<a href="profile?id=${brawlPlayerid}">${brawlPlayer}</a>`,
                prize: brawlPrize,
                power: brawlPlayerpower,
                wins: brawlWins,
                damage: brawlDamage,
                skills: brawlSkills.join('<br>'),
                attacks: `<span class="attacked-${brawlYourattacks}">${brawlYourattacks}</span>`,
                attack10x: brawlAttackbtn,
                wait: brawlWaitforcop
            });
        };
        await Promise.all(Array.from(playerRows).map((raid, index) => buildTable(raid, index)));

        data.sort((a, b) => a.rank - b.rank);
        data.forEach(rowData => {
            const rowElement = document.querySelector("#brawlTable > tbody").insertRow();
            rowElement.innerHTML = Object.values(rowData).map(value => `<td>${value}</td>`).join('');
        });

        if (data.length-1 != document.querySelectorAll('.attacked-10').length){
            document.querySelectorAll('.attacked-10').forEach(function(element) {
                element.closest('tr').style.display = 'none';
            });
        };

        document.querySelector("#hideAttacked").addEventListener('click', async function(){
            document.querySelectorAll('.attacked-10').forEach(function(element) {
                element.closest('tr').style.display = 'none';
            });
        });

        document.querySelector("#showAll").addEventListener('click', async function(){
            document.querySelectorAll('.attacked-10').forEach(function(element) {
                element.closest('tr').style.display = 'revert';
            });
        });

        if (!saCharging){
            document.querySelector("#castSunderArmor").addEventListener('click', async function(){
                const target1 = document.querySelector("#saTarget1").value.replace(/\t/g,'')
                const target2 = document.querySelector("#saTarget2").value.replace(/\t/g,'')
                const target3 = document.querySelector("#saTarget3").value.replace(/\t/g,'')
                const body = `target%5B%5D=${target1}&target%5B%5D=${target2}&target%5B%5D=${target3}&castskillid=21&cast=Cast+Skill`
                if (GM_getValue('auth').match("Full")){
                    await superpost(`cast_skills.php?C=6`,body);
                    window.location = 'closedpvp'
                } else {
                    displayAuthStatus(GM_getValue('auth'));
                };
            });
        };

        if (!pdCharging){
            document.querySelector("#castPoisonDart").addEventListener('click', async function(){
                const target = document.querySelector("#pdTarget").value
                const body = new URLSearchParams({ 'target[]': target, 'castskillid': '16', 'cast': 'Cast Skill' });
                if (GM_getValue('auth').match("Full")){
                    await superpost(`cast_skills.php?C=6`,body);
                    window.location = 'closedpvp'
                } else {
                    displayAuthStatus(GM_getValue('auth'));
                };
            });
        };

        const attack10x = document.querySelectorAll(".attack-10x");
        for (let i = 0; i < attack10x.length; i++) {
            var button = attack10x[i];
            const atkCharId = button.outerHTML.match(/alt="([0-9]+)"/i)[1];
            button.addEventListener("click", async function() {
                await mmplus(`Atk10x|rganame|${server}|${charid}|${atkCharId}`);
            });
        };

        const waitForCop = document.querySelectorAll(".wait-for-cop");
        for (let i = 0; i < waitForCop.length; i++) {
            var button = waitForCop[i];
            const atkCharId = button.outerHTML.match(/alt="([0-9]+)\|.*?"/i)[1];
            const atkCopTime = button.outerHTML.match(/alt=".*?\|(.*?)"/i)[1];
            button.addEventListener("click", async function() {
                await mmplus(`AtkCOP|rganame|${server}|${charid}|${atkCharId}|${atkCopTime}`);
            });
        };
    };
};


async function castSkills(){

    GM_addStyle(`
        .widget-content-area{box-shadow:0 0px 0px 0 rgba(0,0,0,0);}
        .widget-content-area{-webkit-box-shadow:0 0px 0px 0 rgba(0,0,0,0);}
    `)

    const ulElement = document.querySelector("#simpletab");
    const newLiElement = document.createElement("li");
    newLiElement.setAttribute('class','nav-item');
    newLiElement.innerHTML = `<a class="nav-link " href="auto_skiller" role="tab" aria-selected="false">Auto Skiller</a>`;
    ulElement.appendChild(newLiElement);
};


async function support(){
    if (GM_getValue("auth").match("Full")){
        alert('WARNING: Submitting a support ticket will prevent MoxxiMod+ features from running until the support ticket is fully resolved by Outwar');
    };
};


async function oracle(){
    if (document.body.innerHTML.match(/You may view the Oracle's prediction in your message center/i)){
        document.querySelector("#content-header-row").innerHTML = `<img src="https://studiomoxxi.com/moxximod/loading-gif.gif" height="80px" width="80px">`
        const messages = await superfetch('ow_messagecenter');
        const message = messages.match(/view_ow_message\.php\?id=[0-9]+/i);
        window.location.href = message;
    } else {
        return;
    };
};

async function moxxivision(server,serverNo,rgaName,charId){

    await blankOverlay(server,serverNo,rgaName,charId);
    const closeLink = document.body.innerHTML.match(/<a href="([^"]*)">CLOSE<\/a>/i)[1];

    GM_addStyle(`
        #overlayWidget{background-image: url("https://studiomoxxi.com/moxximod/claptrap_loading.webp") !important;background-size: 100% 100% !important;background-attachment: fixed !important;background-position: center !important;background-repeat: no-repeat !important;}
        #blankOverlay{background-color:#181818 !important;}
        h1{font-family:VT323,monospace;letter-spacing:6px;margin-bottom:1rem;}
        #mvRgaSelectDiv{height:300px;overflow-y:auto;overflow-x:hidden;width:600px;border:1px solid #ffffff;background:#000000;}
        .mv-rga-select-table > tbody > tr:hover{transition: 0.1s ease-out;background-color:#0C0C0C;}
        .mv-rga-select-table th, .mv-rga-select-table td {vertical-align:middle;font-family:VT323,monospace;padding: 8px 10px;font-size:14px;cursor:pointer;color:#FFFFFF;}
        .mv-rga-select-table{width:600px;}
        .rga-selected{transition: 0.1s ease-out;background-color:#181818 !important;}
    `);

    document.querySelector("#overlayWidget").innerHTML = `
        <center>
        <h1 style="border:0px SOLID #ffffff;font-size:72px;padding:10px;color:#ffffff;letter-spacing:10px;font-weight:100;font-family:Montserrat,sans-serif;">MOXXIVISION v4</h1>
        <div style="width:600px;text-align:left;">
        <a href="javascript:void(0);" id="mvSelectAll">select all</a> / <a href="javascript:void(0);" id="mvDeselectAll">deselect all</a>
        </div>
        <div id="mvRgaSelectDiv">
        </div><br>
        <a href="javascript:void(0);" class="btn-glitch-fill" id="mvStart">
        <span class="text">
        </a>
        `

    document.querySelector("#mvSelectAll").addEventListener('click', async function(){
        document.querySelectorAll("#mvRgaSelectDiv > table > tbody tr").forEach(tr => {
            tr.classList.add("rga-selected");
        });
    });
    document.querySelector("#mvDeselectAll").addEventListener('click', async function(){
        document.querySelectorAll("#mvRgaSelectDiv > table > tbody tr").forEach(tr => {
            tr.classList.remove("rga-selected");
        });
    });

    if (GM_getValue('savedRgas') == "no sessions saved"){
        await GM_xmlhttpRequest({ url: `https://rampidgaming.outwar.com/account_list.php?rg_sess_id=${rgaName}&G=outwar&owsrv=${serverNo}`,onload: async function(data) {
            const rampid = data.response;
            const rga = rampid.match(/<b>Welcome back (.*?)!<\/b>/i)[1]
            document.querySelector("#mvRgaSelectDiv").innerHTML = `
                <table class="mv-rga-select-table">
                <thead><tr><th>RGA</th><th>SESSION</th></tr></thead>
                <tbody><tr><td id="rganame">${rga}</td><td id="sess">${rgaName}</td></tr></tbody>
                </table>
                `
        }});

    } else {
        const array = GM_getValue('savedRgas').split('><');
        const rows = [];
        const tableRows = async (id) => {
            const rga = id.match(/>([A-Za-z0-9]+)</i)[1];
            const sess = id.match(/rg_sess_id=([A-Za-z0-9]+)/i)[1];
            rows.push(`<tr><td>${rga}</td><td id="sess">${sess}</td></tr>`);
        };
        await Promise.all(array.map(tableRows));
        document.querySelector("#mvRgaSelectDiv").innerHTML = `
            <table class="mv-rga-select-table">
            <thead><tr><th>RGA</th><th>SESSION</th></tr></thead>
            <tbody>${rows.join('')}</tbody>
            </table>
            `
    };

    const rows = document.querySelectorAll('table.mv-rga-select-table tbody tr');
    rows.forEach(tr => {
        tr.addEventListener('click', async function (){
            this.classList.toggle('rga-selected');
        });
    });

    GM_addStyle(`
        #intro {color: white;font-family: "VT323", monospace;}
        [class*="btn-glitch-"]{display: inline-block;font-family:"VT323",monospace;border: 1px solid white;color: white;padding: 10px 13px;min-width:175px;line-height:1.5em;white-space:no-wrap;text-transform:uppercase;cursor:pointer;.text,.decoration{display:inline-block;}
        .decoration{display:inline-block;float:right;}&:hover,&:focus{animation-name:glitch;animation-duration:0.2s;color:white;border:1px solid black;
        .decoration{animation-name: blink;animation-duration:0.1s;animation-iteration-count:infinite;}
        :before{content: " ";width:15px;border: 1px solid black;position:absolute;right:25%;bottom:3px;transform:rotate(35deg)}
        :after{animation-name:shrink;animation-duration:0.5s;animation-iteration-count:1;animation-fill-mode:forwards;width:75%;border:1px solid black;position:absolute;left:0;bottom:5px;}}
        :active {background:none;color:white;.text-decoration{animation-name:none;}
        :before,:after{display:none;}}}
        @keyframes glitch{25%{background-color:red;transform:translateX(-10px);letter-spacing:10px;}35%{background-color:green;transform:translate(10px);}59%{opacity:0;}60%{background-color:blue;transform:translate(-10px);filter:blur(5px);}100%{background-color:black;blur:(5px);}}
        @keyframes blink{50%{opacity:0;}}
        @keyframes shrink{100%{width:10%;}}
        span.blink{animation: blink 0.5s infinite;}
        @keyframes infinite {0%{opactiy:1;}100%{opacity:0;}}
        .slotting-hide{display:none;}
    `)

    document.querySelector("#mvStart").addEventListener('click', async function(){
        const rows = document.querySelectorAll('.rga-selected');
        const array = [];
        const rgas = [];

        if (document.querySelector("#mvRgaSelectDiv > table").rows.length > 2 && rows.length == 0){
            alert ('Please select at least 1 RGA');

        } else if (rows.length == 0){
            this.innerHTML = '<span class="blink">&#x29D6;</span>'
            const rganame = document.querySelector("#rganame").innerHTML

            let array = document.body.innerHTML.match(/option value="[0-9]+"/g).map(i => i.match(/[0-9]+/)[0]);

            if (array.indexOf("0") !== -1) { array = array.slice(0, array.indexOf("0")) };

            array.forEach(async function(id){
                const profile = await superfetch(`profile?id=${id}`);
                const character = profile.match(/<font size="3">(.*?)<\/font>/i)[1];
                const level = profile.match(/<font size="2">Level ([0-9]+) .*?<\/font>/i)[1];
                rgas.push([`rg_sess_id=${rgaName}&suid=${id}&serverid=${serverNo}`,rganame,id,character,level]);
            });

            GM_addStyle(`.mv-rga-cell{display:none;}`)

            await mv(rgas);

        } else {
            this.innerHTML = '<span class="blink">&#x29D6;</span>'
            rows.forEach(tr => { array.push(tr.innerHTML.match(/<td id="sess">(.*?)<\/td>/i)[1]) });
            const get = await mmplus(`IDGrab|rganame|${server}|${array.join(',')}`);
            const parse = get.match(/<tr><td>.*?<\/td><td>.*?<\/td><td>.*?<\/td><td>.*?<\/td><\/tr>/g);
            parse.forEach(async function(i){
                const string = i.match(/<tr><td>(.*?)<\/td><td>(.*?)<\/td><td>(.*?)<\/td><td>.*?<\/td><\/tr>/i)
                const profile = await superfetch(`profile?id=${string[1]}`);
                const character = profile.match(/<font size="3">(.*?)<\/font>/i)[1];
                const level = profile.match(/<font size="2">Level ([0-9]+) .*?<\/font>/i)[1];

                rgas.push([`rg_sess_id=${string[2]}&suid=${string[1]}&serverid=${serverNo}`,string[3],string[1],character,level]);
            });

            if (rows.length == 1){
                GM_addStyle(`.mv-rga-cell{display:none;}`)
            };

            await mv(rgas);
        };
    });


    async function mv(rgas){

        GM_addStyle(`
        #moxxivision{width:100%;height:100%;background:#181818;position:fixed;top:0px;left:0px;z-index:100;}
        div.mv-table-container{text-align:left;display:inline-block;box-shadow: 0 0 10px rgba(0, 0, 0, 1);padding:10px;background-color:#0C0C0C;}
        .mv-table > thead > tr > th{text-transform: uppercase;padding:5px;background-color:#1e1e1e;color:#ffffff;font-weight:100;border:1px solid #000000;}
        .mv-table > tbody > tr > td{padding:5px;color:#ffffff;border:1px solid #000000;}
        .mv-table > tbody > tr > td > img{height:35px;width:35px;border-radius:5px;margin:3px;background-color:#000000;}
        .mv-table > thead > tr > th > img{height:30px;width:30px;border-radius:5px;}
        .mv-table > tbody > tr:nth-child(even){background-color:#1e1e1e;}
        .mv-table > tbody > tr:nth-child(odd){background-color:#2d2d2d;}
        img.mv-augs{width:15px !important;height:15px !important;}
        img.mv-augs-big{width:20px !important;height:20px !important;}
        #mvContent{position:absolute;transition: top 0.5s ease;width:100%;text-align:center;overflow:auto;height:100%;}
        .row1{text-align:center;position:fixed;top:0px;width:100%;z-index:101;background:#0C0C0C;padding:5px;box-shadow: 0 0 5px rgba(0, 0, 0, 1);}
        .row2{text-align:center;position:fixed;top:-200px;width:100%;z-index:102;background:#0C0C0C;padding:5px;transition: top 0.5s ease;box-shadow: 0 0 5px rgba(0, 0, 0, 1);}
        .row2-container{max-width:1200px;margin: 0 auto;}
        #loadingDiv{padding:100px;font-size:62px;color:#ffffff;font-family:Montserrat,sans-serif;letter-spacing:10px;position:fixed;top:0px;text-align:center;height:100%;width:100%;z-index:201;background-image: url("https://studiomoxxi.com/moxximod/claptrap_loading.webp");background-size: 100% 100%;background-attachment: fixed;background-position:center;background-repeat:no-repeat;}
        .mv-btn{letter-spacing:3px;margin:2px;font-size:14px;display:inline-block;font-family:"VT323",monospace;border: 1px solid white;color:#ffffff;padding: 2px 4px;width:200px;text-transform:uppercase;cursor:pointer;text-align:center;transition: top 1s ease;}
        .mv-btn-sub{letter-spacing:3px;margin:2px;font-size:14px;display:inline-block;font-family:"VT323",monospace;border: 1px solid white;color:#ffffff;padding: 1px 2px;width:50px;text-transform:uppercase;cursor:pointer;text-align:center;transition: top 1s ease;}
        .mv-btn:hover,.mv-btn-sub:hover{animation: btn-hover 0.5s ease forwards;}
        @keyframes btn-hover {0%{filter:blur(0px);background-color:#0C0C0C;color:#ffffff;} 100%{filter:blur(1px);background-color:#0C0C0C;color:#ffffff;}}
        .mv-filter{background-color: #0C0C0C;color: #ffffff;border: 1px solid #ffffff;margin-bottom: 0.5rem;width: 100%;font-family: VT323,monospace;font-size: 16px;padding: 7px;}
        .blank-cell{background-color:#0C0C0C !important;color:#0C0C0C !important;border:0px !important;}
        `)

        document.querySelector("#blankOverlay").outerHTML = `
        <div id="moxxivision">
        <!-- Header buttons -->
        <div class="row1" id="mvHeader">
        <a href="javascript:void(0);" class="mv-btn open-btn" alt="character">CHARACTER</a>
        <a href="javascript:void(0);" class="mv-btn open-btn" alt="equipment">EQUIPMENT</a>
        <a href="javascript:void(0);" class="mv-btn open-btn" alt="storage">STORAGE</a>
        <a href="javascript:void(0);" class="mv-btn open-btn" alt="plus">PLUS TABS</a>
        <a href="${closeLink}" class="mv-btn">EXIT</a>
        </div>
        <!-- Character buttons -->
        <div class="row2" id="div-character" style="text-align:center">
        <div class="row2-container">
        <a href="javascript:void(0);" class="mv-btn" id="character-overview">OVERVIEW</a>
        <a href="javascript:void(0);" class="mv-btn" id="character-stats">STATS</a>
        <a href="javascript:void(0);" class="mv-btn" id="character-collections">COLLECTIONS</a>
        <a href="javascript:void(0);" class="mv-btn" id="character-skills">SKILLS</a>
        <a href="javascript:void(0);" class="mv-btn" id="character-underlings">UNDERLINGS</a>
        <a href="javascript:void(0);" class="mv-btn" id="character-god-slayer">GOD SLAYER</a>
        <a href="javascript:void(0);" class="mv-btn" id="character-codex">CODEX</a>
        <a href="javascript:void(0);" class="mv-btn close-btn">CLOSE</a>
        </div>
        </div>
        <!-- Equipment buttons -->
        <div class="row2" id="div-equipment" style="text-align:center">
        <div class="row2-container">
        <a href="javascript:void(0);" class="mv-btn" id="equipment-equipped">EQUIPPED</a>
        <a href="javascript:void(0);" class="mv-btn eq-slot" id="equipment-10">CORE</a>
        <a href="javascript:void(0);" class="mv-btn eq-slot" id="equipment-5">HEAD</a>
        <a href="javascript:void(0);" class="mv-btn eq-slot" id="equipment-6">NECK</a>
        <a href="javascript:void(0);" class="mv-btn eq-slot" id="equipment-3">WEAPON</a>
        <a href="javascript:void(0);" class="mv-btn eq-slot" id="equipment-0">BODY</a>
        <a href="javascript:void(0);" class="mv-btn eq-slot" id="equipment-1">SHIELD</a>
        <a href="javascript:void(0);" class="mv-btn eq-slot" id="equipment-7">BELT</a>
        <a href="javascript:void(0);" class="mv-btn eq-slot" id="equipment-9">PANTS</a>
        <a href="javascript:void(0);" class="mv-btn eq-slot" id="equipment-4">RING</a>
        <a href="javascript:void(0);" class="mv-btn eq-slot" id="equipment-2">FOOT</a>
        <a href="javascript:void(0);" class="mv-btn" id="equipment-chaos-gem">CHAOS GEM</a>
        <a href="javascript:void(0);" class="mv-btn" id="equipment-badge">BADGE</a>
        <a href="javascript:void(0);" class="mv-btn" id="equipment-orbs">ORBS</a>
        <a href="javascript:void(0);" class="mv-btn" id="equipment-rune">RUNE</a>
        <a href="javascript:void(0);" class="mv-btn" id="equipment-booster">BOOSTER</a>
        <a href="javascript:void(0);" class="mv-btn" id="equipment-crests">CRESTS</a>
        <a href="javascript:void(0);" class="mv-btn" id="equipment-augments">AUGMENTS</a>
        <a href="javascript:void(0);" class="mv-btn close-btn">CLOSE</a>
        </div>
        </div>
        <!-- Storage buttons -->
        <div class="row2" id="div-storage" style="text-align:center">
        <div class="row2-container">
        <a href="javascript:void(0);" class="mv-btn" id="storage-backpack">BACKPACK</a>
        <a href="javascript:void(0);" class="mv-btn bp-tab" id="storage-quest-items" alt="quest">QUEST ITEMS</a>
        <a href="javascript:void(0);" class="mv-btn bp-tab" id="storage-orbs" alt="orb">ORBS</a>
        <a href="javascript:void(0);" class="mv-btn bp-tab" id="storage-potions" alt="potion">POTIONS</a>
        <a href="javascript:void(0);" class="mv-btn bp-tab" id="storage-keys" alt="key">KEYS</a>
        <a href="javascript:void(0);" class="mv-btn" id="storage-equipment">EQUIPMENT</a>
        <a href="javascript:void(0);" class="mv-btn" id="storage-vault">VAULT</a>
        <a href="javascript:void(0);" class="mv-btn" id="storage-augments">AUGMENTS</a>
        <a href="javascript:void(0);" class="mv-btn close-btn">CLOSE</a>
        </div>
        </div>
        <!-- Special view buttons -->
        <div class="row2" id="div-plus" style="text-align:center">
        <div class="row2-container">
        <a href="javascript:void(0);" class="mv-btn mv-plus open-btn" id="plus-events" alt="events">EVENT MANAGER</a>
        <a href="javascript:void(0);" class="mv-btn mv-plus" id="plus-item-slotting" alt="slotting">ITEM SLOTTING</a>
        <a href="javascript:void(0);" class="mv-btn mv-plus" id="plus-max-rage">MR OPTIMIZER</a>
        <a href="javascript:void(0);" class="mv-btn close-btn">CLOSE</a>
        </div>
        </div>
        <!-- Events view buttons -->
        <div class="row2" id="div-events" style="text-align:center">
        <div class="row2-container">
        <a href="javascript:void(0);" class="mv-btn woz-top" id="plus-events-war-of-zhul">WAR OF ZHUL</a>
        <a href="javascript:void(0);" class="mv-btn woz-top" id="plus-events-trial-of-power">TRIAL OF POWER</a>
        <a href="javascript:void(0);" class="mv-btn" id="plus-events-holidays">HOLIDAYS</a>
        <a href="javascript:void(0);" class="mv-btn close-btn">CLOSE</a>
        </div>
        </div>
        <!-- Content -->
        <div id="mvContent">
        <span style="border:0px SOLID #ffffff;font-size:62px;position:relative;top:100px;color:#ffffff;letter-spacing:10px;font-weight:100;font-family:Montserrat,sans-serif;">
        <span class="blink">//</span> MOXXIVISION v_4
        </span>
        </div>
        <!-- End -->
        </div>
        `

        var heightHeader = document.querySelector("#mvHeader").clientHeight + 10;
        document.querySelector("#mvContent").setAttribute('style',`top:${heightHeader}px`)

        const open = document.querySelectorAll(".open-btn")
        open.forEach(function(button){
            button.addEventListener('click',async function(){
                const alt = this.outerHTML.match(/alt="([^"]*)"/i)[1];
                var currentPosition = document.getElementById(`div-${alt}`).getBoundingClientRect();
                document.getElementById(`div-${alt}`).style.top = currentPosition.top + 200 + 'px';

                var heightDiv = document.getElementById(`div-${alt}`).clientHeight;
                document.querySelector("#mvContent").style.top = heightDiv + 10 + 'px';

                await new Promise(resolve => setTimeout(resolve, 500));
                const vh = window.innerHeight;
                document.querySelector('#mvContent').style.height = vh - heightDiv - 10 + 'px';
            });
        });

        const close = document.querySelectorAll(".close-btn")
        close.forEach(function(button){
            button.addEventListener('click',async function(){
                const div = this.parentElement.parentElement.outerHTML.match(/id="([^"]*)"/i)[1];
                var currentPosition = document.getElementById(div).getBoundingClientRect();
                document.getElementById(div).style.top = currentPosition.top - 200 + 'px';

                var heightHeader = document.querySelector("#mvHeader").clientHeight + 10;
                document.querySelector("#mvContent").style.top = heightHeader + "px";

                const vh = window.innerHeight;
                document.querySelector('#mvContent').style.height = vh - heightHeader - 10 + 'px';
            });
        });

        document.querySelector("#character-overview").addEventListener('click', async function(){ await mvCharacterOverview(rgas) });
        document.querySelector("#character-stats").addEventListener('click', async function(){ await mvCharacterStats(rgas) });
        document.querySelector("#character-collections").addEventListener('click', async function(){ await mvCharacterCollections(rgas) });
        document.querySelector("#character-skills").addEventListener('click', async function(){ await mvCharacterSkills(rgas) });
        document.querySelector("#character-underlings").addEventListener('click', async function(){ await mvCharacterUnderlings(rgas) });
        document.querySelector("#character-god-slayer").addEventListener('click', async function(){ await mvCharacterGodSlayer(rgas) });
        document.querySelector("#character-codex").addEventListener('click', async function(){ await mvCharacterCodex(rgas) });
        document.querySelector("#equipment-equipped").addEventListener('click', async function(){ await mvEquipmentEquipped(rgas) });
        const slots = Array.from(document.querySelectorAll(".eq-slot"));
        for (let i = 0; i < slots.length; i++) {
            slots[i].addEventListener('click',async function(){
                const slot = 'slot' + this.outerHTML.match(/id="equipment-([0-9]+)"/i)[1];
                await mvEquipmentSlot(rgas,slot);
            });
        };
        document.querySelector("#equipment-chaos-gem").addEventListener('click', async function(){ await mvEquipmentChaosGem(rgas) });
        document.querySelector("#equipment-badge").addEventListener('click',async function(){ await mvEquipmentBadge(rgas) });
        document.querySelector("#equipment-orbs").addEventListener('click',async function(){ await mvEquipmentOrbs(rgas) });
        document.querySelector("#equipment-rune").addEventListener('click',async function(){ await mvEquipmentRune(rgas) });
        document.querySelector("#equipment-booster").addEventListener('click',async function(){ await mvEquipmentBooster(rgas) });
        document.querySelector("#equipment-crests").addEventListener('click',async function(){ await mvEquipmentCrests(rgas) });
        document.querySelector("#equipment-augments").addEventListener('click',async function(){ await mvEquipmentAugments(rgas) });
        document.querySelector("#storage-backpack").addEventListener('click', async function(){ await mvStorageBackpack(rgas) });
        const bpType = Array.from(document.querySelectorAll(".bp-tab"));
        for (let i = 0; i < bpType.length; i++) {
            bpType[i].addEventListener('click', async function(){
                const tab = this.outerHTML.match(/alt="([^"]*)"/i)[1];
                await mvStorageItems(rgas,tab);
            });
        };
        document.querySelector("#storage-equipment").addEventListener('click', async function(){ await mvStorageEquipment(rgas) });
        document.querySelector("#storage-vault").addEventListener('click', async function(){ await mvStorageVault(rgas) });
        document.querySelector("#storage-augments").addEventListener('click', async function(){ await mvStorageAugments(rgas) });
        const tabs = Array.from(document.querySelectorAll(".mv-plus"));
        for (let i = 0; i < tabs.length; i++) {
            tabs[i].addEventListener('click',async function(){
                const string = await mmplus('AuthCheck|rganame');
                const tab = this.outerHTML.match(/id="plus-([^"]*)"/i)[1];
                if (tab == "events"){
                    const events = Array.from(document.querySelectorAll(".woz-top"));
                    for (let i = 0; i < events.length; i++) {
                        events[i].addEventListener('click',async function(){
                            const event = this.innerHTML;
                            await mvEvents(rgas,event,string);
                        });
                    };
                    document.querySelector("#plus-events-holidays").addEventListener('click', async function(){ await mvHolidays(rgas,string) });
                }
                else if (tab == "item-slotting"){ await mvItemSlotting(rgas,string) }
                else if (tab == "max-rage"){ await mvMaxRage(rgas,string) };
            });
        };
    };
};



async function mvCharacterOverview(rgas){
    const endpoints = ['profile','supplies'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const charclass = i.profile.match(/<font size="2">Level [0-9]+ (.*?)<\/font>/i)[1];
        const crew = (i.profile.match(/<a href="\/crew_profile\?id=[0-9]+">(.*?)<\/a>/i) || ['',''])[1];
        const rage = i.profile.match(/<span class="toolbar_rage">[\n\r](.*?) <\/span>/i)[1];
        const exp = i.profile.match(/TOTAL EXPERIENCE.*[\n\r].*<font size="2">(.*)<\/font>/i)[1];
        const tolvl = i.profile.match(/Needed to Level:<\/b><\/td><td>(.*?)<\/td><\/tr><tr>/i)[1];
        const today = i.profile.match(/<tr><td><b>Growth Today:<\/b><\/td><td>(.*)<\/td><\/tr><tr><td><b>Per Turn/i)[1];
        const yesterday = i.profile.match(/GROWTH YESTERDAY.*[\n\r].*<font size="2">(.*)<\/font>/i)[1];
        const strength = i.profile.match(/role="progressbar" style="width: ([0-9]+)%; height: 8px;"/i)[1];
        const supplies = i.supplies.match(/<img border="0" src="images\/suppliestriangle\.gif" width="11" height="11">[\n\r](.*)%<\/td>/i)[1];
        const gold = i.profile.match(/<tr><td><b>Gold:<\/b><\/td><td>(.*)<\/td><\/tr>/i)[1];
        rows.push(`<tr>${i.static}<td>${charclass}</td><td>${crew}</td><td>${rage}</td><td>${exp}</td><td>${tolvl}</td><td>${today}</td><td>${yesterday}</td><td>${strength}</td><td>${supplies}</td><td>${gold}</td></tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container"><table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>class</th><th>crew</th><th>rage</th><th>experience</th><th>to level</th><th>growth today</th><th>yesterday</th><th>strength</th><th>supplies</th><th>gold</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvCharacterStats(rgas){
    const endpoints = ['profile','home'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const mr = i.profile.match(/Maximum:<\/b><\/td><td>(.*?)<\/td><\/tr>/i)[1];
        const power = i.profile.match(/TOTAL POWER.*[\n\r].*<font size="2">(.*)<\/font><\/b><\/td>/i)[1];
        const ele = i.profile.match(/ELEMENTAL ATTACK.*[\n\r].*<font size="2">(.*)<\/font>/i)[1];
        const atk = i.profile.match(/ATTACK.*[\n\r].*<font size="2">(.*)<\/font>/i)[1];
        const hp = i.profile.match(/HIT POINTS.*[\n\r].*<font size="2">(.*)<\/font>/i)[1];
        const chaos = i.profile.match(/CHAOS DAMAGE.*[\n\r].*<font size="2">(.*)<\/font>/i)[1];
        const res1 = i.home.match(/onmouseout="kill\(\)">Holy Resist:<\/b>.*[\n\r].*[\n\r].*[\n\r].*[\n\r](.*)<\/font>/i)[1];
        const res2 = i.home.match(/onmouseout="kill\(\)">Arcane Resist:<\/b>.*[\n\r].*[\n\r].*[\n\r].*[\n\r](.*)<\/font>/i)[1];
        const res3 = i.home.match(/onmouseout="kill\(\)">Shadow Resist:<\/b>.*[\n\r].*[\n\r].*[\n\r].*[\n\r](.*)<\/font>/i)[1];
        const res4 = i.home.match(/onmouseout="kill\(\)">Fire Resist:<\/b>.*[\n\r].*[\n\r].*[\n\r].*[\n\r](.*)<\/font>/i)[1];
        const res5 = i.home.match(/onmouseout="kill\(\)">Kinetic Resist:<\/b>.*[\n\r].*[\n\r].*[\n\r].*[\n\r](.*)<\/font>/i)[1];
        const rpt = i.profile.match(/<p class="top-rage" ONMOUSEOVER="statspopup\(event,'<tr><td><b>Per Turn:<\/b><\/td><td>(.*?)<\/td>/i)[1];
        const ept = i.profile.match(/<b>Growth Today:<\/b><\/td><td>.*?<\/td><\/tr><tr><td><b>Per Turn:<\/b><\/td><td>(.*?)<\/td>/i)[1];
        const wilderness = i.profile.match(/WILDERNESS LEVEL.*[\n\r].*<font size="2">(.*)<\/font>/i)[1];
        rows.push(`<tr>
        ${i.static}
        <td>${mr}</td>
        <td>${power}</td>
        <td>${ele}</td>
        <td>${atk}</td>
        <td>${hp}</td>
        <td>${chaos}</td>
        <td><font color="#00FFFF">${res1}</td>
        <td><font color="#FFFF00">${res2}</td>
        <td><font color="#7e01bc">${res3}</td>
        <td><font color="#FF0000">${res4}</td>
        <td><font color="#00FF00">${res5}</td>
        <td>${rpt}</td>
        <td>${ept}</td>
        <td>${wilderness}</td>
        </tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container"><table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>max rage</th><th>power</th><th>ele</th><th>atk</th><th>hp</th><th>chaos</th><th>res</th><th>res</th><th>res</th><th>res</th><th>res</th><th>rpt</th><th>ept</th><th>wilderness</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvCharacterSkills(rgas){
    const endpoints = ['home','cast_skills?C=7'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const wall = i.skills.match(/alt="Shield Wall"/i) ? "X" : "";
        const slayer = i.skills.match(/alt="God Slayer"/i) ? "X" : "";
        const grind = i.skills.match(/alt="Daily Grind"/i) ? "X" : "";
        const influence = i.skills.match(/alt="Triworld Influence"/i) ? "X" : "";
        const skillclass = i.home.match(/Level [0-9]+ ([A-Za-z]+)/i)[1];
        const skillpoints = i.home.match(/Skill:<\/b><\/td><td>([0-9]+)<\/td>/i)[1];
        const parser = new DOMParser();
        const x = parser.parseFromString(i.home, 'text/html');
        const active = x.querySelector("#content-header-row").innerHTML.match(/<img.*?Cast By.*?>/g) || [];
        rows.push(`<tr>${i.static}<td>${skillclass}</td><td>${skillpoints}</td><td>${wall}</td><td>${slayer}</td><td>${grind}</td><td>${influence}</td><td style="max-width:750px;">${active.join('')}</td></tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container"><table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>class</th><th>skill points</th><th><img src="images/skills/shieldwall.png"></th><th><img src="images/skills/GodSlayerSkill.png"></th><th><img src="images/skills/dailygrind.png"></th><th><img src="images/skills/influenceskill.png"></th><th>active skills</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvCharacterUnderlings(rgas){
    const endpoints = ['profile','home'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const parser = new DOMParser()
        const x = parser.parseFromString(i.profile, 'text/html');
        const table = x.querySelector("#UnderlingTable");
        const lings = table.rows.length-1
        const loyalty = i.home.match(/onmouseout="kill\(\)">Underling Loyalty:<\/b>.*[\n\r].*[\n\r].*[\n\r].*[\n\r](.*)<\/font>/i)[1];

        const tableRows = table.querySelectorAll("tbody tr");
        let exp = 0;
        let power = 0;
        tableRows.forEach(row => {
            exp += parseInt(row.cells[2].innerText.replace(/,/g, ''));
            power += parseInt(row.cells[3].innerText.replace(/,/g, ''));
        });
        rows.push(`<tr>${i.static}<td>${lings}</td><td>${exp.toLocaleString()}</td><td>${power.toLocaleString()}</td><td>${loyalty}</td></tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container"><table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>lings</th><th>total experience</th><th>total power</th><th>loyalty enhancement</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvCharacterGodSlayer(rgas){
    const endpoints = ['profile'];
    const array = await mvFetch(rgas,endpoints);
    const allgods = await info("Array of all gods");
    const rows = [];
    const table = async (i) => {
        const crew = (i.profile.match(/<a href="\/crew_profile\?id=[0-9]+">(.*?)<\/a>/i) || ['',''])[1];
        const parser = new DOMParser()
        const x = parser.parseFromString(i.profile, 'text/html');
        const completed = (x.querySelector("#divProfile").innerHTML.match(/<b>.*?<\/b><br>First Slayed/g) || ['<b></b>']).map(i => i.match(/<b>(.*?)<\/b>/)[1]);
        const needed = allgods.filter(item => !completed.includes(item));
        const list = needed.map(i => i.replace(/(,| ,| the|The| of).*/gi, ''));
        rows.push(`<tr>${i.static}<td>${crew}</td><td>${allgods.length - needed.length}</td><td class="filt" style="max-width:750px;">${list.join(', ')}</td></tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <input type="text" id="filter" class="mv-filter" placeholder="Filter missing gods..."><br>
    <table class="mv-table sortable filterable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>crew</th><th>slayer lvl</th><th>gods missing</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await filterTables();
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvCharacterCollections(rgas){
    const endpoints = ['collections'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const parser = new DOMParser()
        const x = parser.parseFromString(i.collections, 'text/html');
        const anjou = (x.querySelector("#divCollections > div.row > div:nth-child(1) > div > div > div.user-info.w-100.pr-3 > ul").innerHTML.match(/img/g) || []).length + " / 3"
        const reikar = (x.querySelector("#divCollections > div.row > div:nth-child(2) > div > div > div.user-info.w-100.pr-3 > ul").innerHTML.match(/img/g) || []).length + " / 3"
        const lorren = (x.querySelector("#divCollections > div.row > div:nth-child(3) > div > div > div.user-info.w-100.pr-3 > ul").innerHTML.match(/img/g) || []).length + " / 3"
        const lucile = (x.querySelector("#divCollections > div.row > div:nth-child(4) > div > div > div.user-info.w-100.pr-3 > ul").innerHTML.match(/img/g) || []).length + " / 3"
        const weima = (x.querySelector("#divCollections > div.row > div:nth-child(5) > div > div > div.user-info.w-100.pr-3 > ul").innerHTML.match(/img/g) || []).length + " / 3"
        const souma = (x.querySelector("#divCollections > div.row > div:nth-child(6) > div > div > div.user-info.w-100.pr-3 > ul").innerHTML.match(/img/g) || []).length + " / 3"
        const vanisha = (x.querySelector("#divCollections > div.row > div:nth-child(7) > div > div > div.user-info.w-100.pr-3 > ul").innerHTML.match(/img/g) || []).length + " / 3"
        const drolba = (x.querySelector("#divCollections > div.row > div:nth-child(8) > div > div > div.user-info.w-100.pr-3 > ul").innerHTML.match(/img/g) || []).length + " / 3"
        const quibel = (x.querySelector("#divCollections > div.row > div:nth-child(9) > div > div > div.user-info.w-100.pr-3 > ul").innerHTML.match(/img/g) || []).length + " / 3"
        rows.push(`<tr>${i.static}<td>${anjou}</td><td>${reikar}</td><td>${lorren}</td><td>${lucile}</td><td>${weima}</td><td>${souma}</td><td>${vanisha}</td><td>${drolba}</td><td>${quibel}</td></tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container"><table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>anjou</th><th>reikar</th><th>lorren</th><th>lucile</th><th>weima</th><th>souma</th><th>vanisha</th><th>drolba</th><th>quibel</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvCharacterCodex(rgas){
    const endpoints = ['changefaction'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const completed = (i.changefaction.match(/Triworld Codex Chapter [0-9]+<br>/g) || ['0']).map(i => parseInt(i.match(/[0-9]+/i)))
        const incomplete = [];
        for (let i = 1; i <= 50; i++) {
            if (!completed.includes(i)) { incomplete.push(i) };
        };
        rows.push(`<tr>${i.static}<td>${completed.length}</td><td class="filt">${incomplete.join(',')}</td></tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <input type="text" id="filter" class="mv-filter" placeholder="Filter missing codex..."><br>
    <table class="mv-table sortable filterable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>influence</th><th>incomplete codex</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await filterTables();
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvEquipmentEquipped(rgas,slot){
    const endpoints = ['equipment?r=0'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const slotsize = 'height:35px;width:35px'
        const core = i.equipment.match(/<.*?'slot10'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const head = i.equipment.match(/<.*?'slot5'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const neck = i.equipment.match(/<.*?'slot6'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const weapon = i.equipment.match(/<.*?'slot3'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const body = i.equipment.match(/<.*?'slot0'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const shield = i.equipment.match(/<.*?'slot1'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const belt = i.equipment.match(/<.*?'slot7'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const pants = i.equipment.match(/<.*?'slot9'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const ring = i.equipment.match(/<.*?'slot4'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const foot = i.equipment.match(/<.*?'slot2'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const chaosgem = i.equipment.match(/<.*?'slot17'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const badge = i.equipment.match(/<.*?'slot12'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const rune = i.equipment.match(/<.*?'slot11'.*?>/i) || `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const orbs = i.equipment.match(/<.*?'slot8'.*?>/g) || [];
        const orb1 = orbs.length > 0 ? orbs[0] : `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const orb2 = orbs.length > 1 ? orbs[1] : `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        const orb3 = orbs.length > 2 ? orbs[2] : `<div style="${slotsize};border-radius:5px;margin-right:5px;background-color:#000000;"></div>`
        rows.push(`<tr>${i.static}<td>${core}</td><td>${head}</td><td>${neck}</td><td>${weapon}</td><td>${body}</td><td>${shield}</td><td>${belt}</td><td>${pants}</td><td>${ring}</td><td>${foot}</td><td>${chaosgem}</td><td>${badge}</td><td>${rune}</td><td>${orb1}</td><td>${orb2}</td><td>${orb3}</td></tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>CRE</th><th>HED</th><th>NCK</th><th>WEP</th><th>BDY</th><th>SHD</th><th>BELT</th><th>PNT</th><th>RNG</th><th>FOT</th><th>GEM</th><th>BDG</th><th>RNE</th><th>ORB</th><th>ORB</th><th>ORB</th></tr></thead>
    <tbody>${rows.join('').replace(/onclick="[^"]*"/g,'')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvEquipmentSlot(rgas,slot){
    const endpoints = ['equipment?r=0'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const regex = new RegExp(`<.*?'${slot}'.*?>`,'i');
    const table = async (i) => {
        const itemid = parseInt((i.equipment.match(regex) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
        const s = await mvItemSpec(itemid);
        rows.push('<tr>' + i.static + s.name + s.img + s.augs + s.gems + s.atk + s.hp + s.elemental + s.ele6 + s.resist + s.res6 + s.vile + s.rpt + s.ept + s.rampage + s.critical + s.mr + s.block + s.eleblock + s.ps + '</tr>');
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>name</th><th>img</th><th>augs</th><th>gem</th><th>atk</th><th>hp</th><th>ele</th><th><font color="#f441be">chs</th><th>res</th><th><font color="#f441be">res</th><th>vle</th><th>rpt</th><th>ept</th><th>rmp</th><th>crt</th><th>mr</th><th>blk</th><th><font color="#00FF00">blk</th><th>ps</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvEquipmentChaosGem(rgas){
    const endpoints = ['equipment?r=0'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const itemid = parseInt((i.equipment.match(/<.*?'slot17'.*?>/i) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
        const s = await mvItemSpec(itemid);
        rows.push('<tr>' + i.static + s.name + s.img + s.ele6 + s.rampage + s.critical + s.mr + '</tr>');
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>name</th><th>img</th><th>chaos</th><th>rampage</th><th>critical</th><th>max rage</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvEquipmentBadge(rgas){
    const endpoints = ['equipment?r=0'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const itemid = parseInt((i.equipment.match(/<.*?'slot12'.*?>/i) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
        const s = await mvItemSpec(itemid);
        rows.push('<tr>' + i.static + s.name + s.img + s.atk + s.hp + s.elemental + '</tr>');
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>name</th><th>img</th><th>atk</th><th>hp</th><th>elemental</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvEquipmentOrbs(rgas){
    const endpoints = ['equipment?r=0'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const orbs = i.equipment.match(/<.*?'slot8'.*?>/g) || [];
        const orb1 = orbs.length > 0 ? orbs[0].match(/event,'([0-9]+)'/i)[1] : 0
        const orb2 = orbs.length > 1 ? orbs[1].match(/event,'([0-9]+)'/i)[1] : 0
        const orb3 = orbs.length > 2 ? orbs[2].match(/event,'([0-9]+)'/i)[1] : 0
        const ids = [orb1,orb2,orb3];
        let names = [];
        let imgs = [];
        let elemental = 0; let atk = 0; let hp = 0; let rpt = 0; let ept = 0; let mr = 0; let ele6 = 0;
        for (let i = 0; i < 3; i++) {
            const itemid = parseInt(ids[i]);
            const s = await mvItemSpec(itemid);
            names.push(s.name);
            imgs.push(s.img);
            elemental += parseInt(s.elemental.replace(/<.*?>/g,''));
            atk += parseInt(s.atk.replace(/<.*?>/g,''));
            hp += parseInt(s.hp.replace(/<.*?>/g,''));
            rpt += parseInt(s.rpt.replace(/<.*?>/g,''));
            ept += parseInt(s.ept.replace(/<.*?>/g,''));
            mr += parseInt(s.mr.replace(/<.*?>/g,''));
            ele6 += parseInt(s.ele6.replace(/<.*?>/g,''));
        };
        rows.push('<tr>' + i.static + imgs.join('') + names.join('') + `<td>${mr}</td><td>${elemental}</td><td>${atk}</td><td>${hp}</td><td>${rpt}</td><td>${ept}</td><td>${ele6}</td></tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>img</th><th>img</th><th>img</th><th>orb 1</th><th>orb 2</th><th>orb 3</th><th>mr</th><th>ele</th><th>atk</th><th>hp</th><th>rpt</th><th>ept</th><th>chaos</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvEquipmentRune(rgas){
    const endpoints = ['equipment?r=0'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const itemid = parseInt((i.equipment.match(/<.*?'slot11'.*?>/i) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
        const s = await mvItemSpec(itemid);
        rows.push('<tr>' + i.static + s.name + s.img + s.elemental + '</tr>');
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>name</th><th>img</th><th>elemental</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvEquipmentBooster(rgas){
    const endpoints = ['equipment?r=0'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const itemid = parseInt((i.equipment.match(/<.*?'slot18'.*?>/i) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
        const s = await mvItemSpec(itemid);
        rows.push('<tr>' + i.static + s.img + s.name + '</tr>');
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>img</th><th>booster</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvEquipmentCrests(rgas){
    const endpoints = ['equipment?r=0'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const itemid1 = parseInt((i.equipment.match(/<.*?'slot13'.*?>/i) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
        const itemid2 = parseInt((i.equipment.match(/<.*?'slot14'.*?>/i) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
        const itemid3 = parseInt((i.equipment.match(/<.*?'slot15'.*?>/i) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
        const itemid4 = parseInt((i.equipment.match(/<.*?'slot16'.*?>/i) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
        const s1 = await mvItemSpec(itemid1);
        const s2 = await mvItemSpec(itemid2);
        const s3 = await mvItemSpec(itemid3);
        const s4 = await mvItemSpec(itemid4);
        rows.push('<tr>' + i.static + s1.img + s2.img + s3.img + s4.img + s1.name + s2.name + s3.name + s4.name + '</tr>');
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>img</th><th>img</th><th>img</th><th>img</th><th>class</th><th>ferocity</th><th>preservation</th><th>affliction</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvEquipmentAugments(rgas){
    const endpoints = ['equipment?r=0'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        let allaugs = '';
        for (let n = 0; n <= 10; n++) {
            const regex = new RegExp(`<.*?'slot${n}'.*?>`);
            const id = parseInt((i.equipment.match(regex) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
            const item = await superfetch(`item_rollover.php?id=${id}`);
            const augs = item.match(/<img width="[0-9]+" style="[^"]*" src="[^"]*" ONMOUSEOVER="itempopup\(event,'[0-9]+_[0-9]+'\)" ONMOUSEOUT="kill\(\)">/g) || [];
            allaugs += augs.join('').replace(/>/g,' class="mv-augs-big">');
        };
        const count = allaugs.match(/mv-augs-big/g).length
        rows.push(`<tr>${i.static}<td>${count}</td><td style="max-width:615px;">${allaugs}</td></tr>`)
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>count</th><th>augments</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvStorageBackpack(rgas){
    const endpoints = ['ajax/backpackcontents.php?tab=regular'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const match = i.regular.replace(/\s+/g, ' ').replace(/[\n\r]/g,'').match(/src="[^"]*" alt="[^"]*" ONMOUSEOVER="itempopup\(event,'[0-9]+'\)"/g) || [];
        const items = match.length < 250 ? match.map(i => `<img ${i} onmouseout="kill()" class="mv-selectable">`) : ['Too many items to display'];
        rows.push('<tr>' + i.static + '<td style="max-width:615px">' + items.join('') + '</td></tr>')
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>backpack items</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `

    const selectable = document.querySelectorAll('img.mv-selectable');
    for (var i = 0; i < selectable.length; i++){
        const item = selectable[i];
        item.addEventListener('click', async function(){
            item.classList.toggle('mv-backpack-selected')
        })
    }

    await sortableTables();

    document.querySelector("#loadingDiv").remove();
};

async function mvStorageItems(rgas,tab){
    const endpoints = [`ajax/backpackcontents.php?tab=${tab}`];
    const array = await mvFetch(rgas,endpoints);
    const headerArray = [];

    const itemsList = async (i) => {
        const itemsParse = i[tab].replace(/\s+/g, ' ').replace(/[\n\r]/g,'').replace(/'/g,'').match(/src="[^"]*" alt="[^"]*"/g);
        if (itemsParse){
            for (let n = 0; n < itemsParse.length; n++) {
                headerArray.push(itemsParse[n]);
            };
        };
    };
    await Promise.all(array.map(itemsList));

    headerArray.sort((a, b) => {
        const altA = a.match(/alt="([^"]*)"/)[1];
        const altB = b.match(/alt="([^"]*)"/)[1];
        return altA.localeCompare(altB);
    });

    const header = ([...new Set(headerArray)]).map(i => `<th><img ${i.match(/src="[^"]*"/i)} onmouseover="statspopup(event,'${i.match(/alt="([^"]*)"/i)[1]}')" onmouseout="kill()"></th>`);

    const noOfTables = Math.ceil(header.length/18);

    const headers = []
    const rows = []

    for (let i = 0; i < noOfTables; i++) {

        const slicedHeader = header.slice(i*18,(i+1)*18);
        headers[i+1] = slicedHeader;

        const row = []

        const table = async (a) => {

            const names = slicedHeader.join('').match(/event,'[^']*'/g).map(p => p.match(/'([^']*)'/)[1]);
            const item = a[tab].replace(/\s+/g, ' ').replace(/[\n\r]/g,'').replace(/'/g,'');

            let cells = a.static;

            for (let n = 0; n < names.length; n++) {
                const regex = new RegExp(`data-itemidqty="[0-9]+" data-name="${names[n]}"`);
                const count = (item.match(regex) || ['itemidqty="0"']).map(m => m.match(/itemidqty="([0-9]+)"/)[1]);

                cells += '<td>' + count + '</td>';
            };

            row.push('<tr>' + cells + '</tr>');
        };
        await Promise.all(array.map(table));

        rows[i+1] = row;
    };
    document.querySelector("#mvContent").innerHTML = `
    <span id="tableNoSpan"></span>
    <div class="mv-table-container" id="mv-table-container">
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th>${headers[1].join('')}</tr></thead>
    <tbody>${rows[1].join('')}</tbody>
    </table></div></div>
    `

    if (noOfTables > 1){
        const tableLinks = [];

        for (let i = 0; i < noOfTables; i++) {
            tableLinks.push(`<a href="javascript:void(0);" class="mv-btn-sub" style="margin-bottom:10px;" id="items-table-${i+1}">${i+1}</a>`)
        };
        document.querySelector("#tableNoSpan").innerHTML = `<center>${tableLinks.join('')}</center>`

        for (let i = 0; i < noOfTables; i++) {
            document.querySelector(`#items-table-${i+1}`).addEventListener('click', async function(){
                document.querySelector("#mv-table-container").innerHTML = `
                <table class="mv-table sortable">
                <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th>${headers[i+1].join('')}</tr></thead>
                <tbody>${rows[i+1].join('')}</tbody>
                </table>
                `
                await sortableTables();
            });
        };
    };
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
}

async function mvStorageEquipment(rgas){
    const endpoints = ['augmentequip'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    let tableMsg = ''
    const table = async (i) => {
        if (i.augmentequip.match(/<h1>Manage Augments<\/h1>/i)){;
            const items = i.augmentequip.match(/<img style="max-width:40px;max-height:40px" border="0" src="[^"]*" onmouseover="itempopup\(event,'[0-9]+'\)" onmouseout="kill\(\)">/g)
            if (items){
                rows.push('<tr>' + i.static + '<td style="width:650px">' + items.join('') + '</td></tr>')[1]
            };
        } else {
            tableMsg = '<i>Equipment will only display for the originating RGA because security word is required to access items</i>'
        };
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <center><font color="#2D2D2D">${tableMsg}</font></center>
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>all equipment</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
}

async function mvStorageVault(rgas){
    const endpoints = ['vault'];
    const array = await mvFetch(rgas,endpoints);
    let tableMsg = ''
    const rows = [];
    const table = async (i) => {
        if (i.vault.match(/Currently Storing/i)){;
            const match = i.vault.replace(/[\n\r]/g,'').replace(/.*images\/vault_inventory\.gif/i,'').match(/src="[^"]*" ONMOUSEOVER="itempopup\(event,'[0-9]+'\)"/g)
            if (match){
                const items = match.map(m => `<img ${m} onmouseout="kill()">`);
                rows.push('<tr>' + i.static + '<td style="width:650px">' + items.join('') + '</td></tr>')[1]
            };
        } else {
            tableMsg = '<i>Vault items will only display for the originating RGA because security word is required to access items</i>'
        };
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <center><font color="#2D2D2D">${tableMsg}</font></center>
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>all equipment</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};

async function mvStorageAugments(rgas){
    const endpoints = ['augmentequip'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    let tableMsg = ''
    const table = async (i) => {
        if (i.augmentequip.match(/<h1>Manage Augments<\/h1>/i)){;
            const match = i.augmentequip.match(/width="20" height="20" src="[^"]*" onmouseover="itempopup\(event,'[0-9]+'\)"/g)
            if (match){
                const items = match.map(m => `<img ${m} onmouseout="kill()">`);
                rows.push('<tr>' + i.static + '<td style="width:650px">' + items.join('') + '</td></tr>')[1]
            };
        } else {
            tableMsg = '<i>Augments will only display for the originating RGA because security word is required to access items</i>'
        };
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container">
    <center><font color="#2D2D2D">${tableMsg}</font></center>
    <table class="mv-table sortable">
    <thead><tr><th>char</th><th class="mv-rga-cell">rga</th><th>lvl</th><th>all augments</th></tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    document.querySelector("#loadingDiv").remove();
};



async function mvItemSlotting(rgas,string){
    document.querySelector("#mvContent").innerHTML = `
    <div class="mv-table-container" id="item-slotting-div">
    <input type="text" id="itemLink" class="mv-filter" style="width:800px" placeholder="Link to item you are slotting...">
    </div>
    `

    document.querySelector("#itemLink").addEventListener('input', async function() {
        const input = document.querySelector("#itemLink").value;
        const link = input.match(/itemlink\?id=[0-9]+/i);

        if (link){

            const itemid = link.toString().match(/[0-9]+/);

            const sNew = await mvItemSpec(itemid);
            const imgNew = sNew.img.replace('<td>','').replace('</td>','');
            const nameNew = sNew.name.replace(/<td.*?>/,'').replace('</td>','');
            const eleNew = parseInt(sNew.elemental.replace(/<td.*?>/,'').replace('</td>','').replace(/,/g,''));
            const mrNew = parseInt(sNew.mr.replace(/<td.*?>/,'').replace('</td>','').replace(/,/g,''));

            const slotName = ['body','shield','foot','weapon','ring','head','neck','belt','','pants','core'];
            const slot = slotName.indexOf(sNew.slot);

            if (!string.match('Full')){ rgas = rgas.slice(0, 2) };
            const endpoints = ['profile','equipment?r=0'];
            const array = await mvFetch(rgas,endpoints);
            const rows = [];
            const regex = new RegExp(`<.*?'slot${slot}'.*?>`,'i');

            const table = async (i) => {
                const mrChar = i.profile.match(/Maximum:<\/b><\/td><td>(.*?)<\/td><\/tr>/i)[1];
                const eleChar = i.profile.match(/ELEMENTAL ATTACK.*[\n\r].*<font size="2">(.*)<\/font>/i)[1];
                const itemid = parseInt((i.equipment.match(regex) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
                const s = await mvItemSpec(itemid);
                const imgCurrent = s.img.replace(/<td.*?>/,'').replace('</td>','');
                const nameCurrent = s.name.replace(/<td.*?>/,'').replace('</td>','');
                const eleCurrent = parseInt(s.elemental.replace(/<td.*?>/,'').replace('</td>','').replace(/,/g,''));
                const mrCurrent = parseInt(s.mr.replace(/<td.*?>/,'').replace('</td>','').replace(/,/g,''));
                const cloned = s.cloned ? " [cloned]" : '';
                rows.push(`<tr>
                ${i.static}
                <td>${eleChar.toLocaleString()}</td>
                <td>${mrChar.toLocaleString()}</td>
                <td class="blank-cell"></td>
                <td>${imgCurrent}</td>
                <td style="max-width:200px">${nameCurrent}${cloned}</td>
                <td>${eleCurrent.toLocaleString()}</td>
                <td>${mrCurrent.toLocaleString()}</td>
                <td class="blank-cell"></td>
                <td>${imgNew}</td>
                <td style="max-width:200px">${nameNew}</td>
                <td>${eleNew.toLocaleString()}</td>
                <td>${mrNew.toLocaleString()}</td>
                <td class="blank-cell"></td>
                <td>${(eleNew-eleCurrent).toLocaleString()}</td>
                <td>${(mrNew-mrCurrent).toLocaleString()}</td>
                </tr>`);
            };
            await Promise.all(array.map(table));
            document.querySelector("#item-slotting-div").innerHTML = `
            <div id="banner"></div>
            <table class="mv-table sortable">
            <thead><tr>
            <th>character</th>
            <th class="mv-rga-cell">rga</th>
            <th>lvl</th>
            <th>tot ele</th>
            <th>tot mr</th>
            <th class="blank-cell"></th>
            <th>img</th>
            <th>current item</th>
            <th>ele</th>
            <th>mr</th>
            <th class="blank-cell"></th>
            <th>img</th>
            <th>new item</th>
            <th>ele</th>
            <th>mr</th>
            <th class="blank-cell"></th>
            <th>ele change</th>
            <th>mr change</th>
            </tr></thead>
            <tbody>${rows.join('')}</tbody>
            `
            await sortableTables();
            if (!string.match('Full')){ await mvNotSpecial("ITEM SLOTTING") };
            document.querySelector("#loadingDiv").remove();
        } else {
            alert('Invalid item link entered');
        };
    });
};

async function mvMaxRage(rgas,string){
    const endpoints = ['home','equipment?r=0'];
    if (!string.match('Full')){ rgas = rgas.slice(0, 2) };
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const mr = i.home.match(/Maximum:<\/b><\/td><td>(.*?)<\/td><\/tr>/i)[1];
        const charclass = i.home.match(/<span class="t-uppercontent">Level [0-9]+ [A-Za-z]+ (.*?)<\/span>/i)[1]

        const en = i.home.replace(/<[^>]+>/g, '').replace(/\r?\n|\r/g, '').replace(/,/g,'').match(/Maximum Rage:([0-9]+) \/([0-9]+)/i);
        const upgraded = parseInt(en[1]);
        const max = parseInt(en[2]);
        const available = max - upgraded;

        let mrFromItems = 0;
        let mrFromGems = 0;
        let missingGems = 40;
        let costToGem = 0;
        for (let n = 0; n <= 10; n++) {
            if (n != 8){
                const regex = new RegExp(`<.*?'slot${n}'.*?>`);
                const id = parseInt((i.equipment.match(regex) || [`event,'0'`])[0].match(/event,'([0-9]+)'/i)[1]);
                const item = await mvItemSpec(id);
                const rarity = item.name.match(/color:#(\w{6})/i)[1]
                const itemMr = parseInt(item.mr.replace(/<td.*?>/,'').replace('</td>','').replace(/,/g,''))

                mrFromItems += itemMr;
                const gems = parseInt(item.gems.replace(/<td.*?>/,'').replace('</td>',''));

                let multiplier = gems == 3 ? 0.15 : gems == 2 ? 0.3225 : gems == 1 ? 0.520875 : gems == 0 ? 0.74900625 : 0;

                if (charclass == "Monster"){ multiplier *= 1.1; }
                else if (charclass == "Pop Star"){ multiplier *= 1.05; };

                mrFromGems += (itemMr * multiplier);

                missingGems -= gems

                const upgrades = await info("Cost to Gem");
                costToGem += upgrades[rarity][gems];
            };
        };

        const maxMr = Math.ceil(mrFromGems) + parseInt(mr.replace(/,/g,'')) + available;

        const perPoint = missingGems == 0 ? 0 : Math.ceil(mrFromGems/costToGem)

        rows.push(`<tr>
        ${i.static}
        <td>${charclass}</td>
        <td>${mr}</td>
        <td>${upgraded.toLocaleString()}</td>
        <td>${available.toLocaleString()}</td>
        <td>${missingGems}</td>
        <td>${(Math.ceil(mrFromGems) + available).toLocaleString()}</td>
        <td>${costToGem.toLocaleString()}</td>
        <td>${maxMr.toLocaleString()}</td>
        <td>${perPoint}</td>
        </tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div id="banner"></div>
    <div class="mv-table-container"><table class="mv-table sortable">
    <thead><tr>
    <th>char</th>
    <th class="mv-rga-cell">rga</th>
    <th>lvl</th>
    <th>class</th>
    <th>max rage</th>
    <th>char upgrades</th>
    <th>upgrades available</t>
    <th>missing gems</th>
    <th>max gains</th>
    <th>full gem cost</th>
    <th>mr if maxed</th>
    <th>mr per point</th>
    </tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `
    await sortableTables();
    if (!string.match('Full')){ await mvNotSpecial("MAX RAGE") };
    document.querySelector("#loadingDiv").remove();
};

async function mvEvents(rgas,event,string){
    const peram = event == "WAR OF ZHUL" ? "woz" : "top"
    const qItemLong = event == "WAR OF ZHUL" ? "Summoning Shard" : "Trial Insignia"
    const qItemShort = event == "WAR OF ZHUL" ? "shards" : "insignias"
    const qItemImg = event == "WAR OF ZHUL" ? "images/warshard.jpg" : "images/items/trialinsignia.jpg"

    let runsLeft;
    const eventPage = await superfetch(`event?eventid=${peram}`);
    if (eventPage.match('START COUNTDOWN')){
        runsLeft = 31;
    } else {
    const timer = parseInt(eventPage.match(/countdown = ([0-9]+)/i)[1])*1000;
    const now = ((new Date().getTime()) - 18000000);
    runsLeft = (timer-now)/3600000/10.8;
    };

    if (!string.match('Full')){ rgas = rgas.slice(0, 2) };
    const endpoints = ['profile','ajax/backpackcontents.php?tab=quest','ajax/backpackcontents.php?tab=potion'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const regex = new RegExp(`data-itemidqty="[0-9]+" data-name="${qItemLong}"`);
    const table = async (i) => {
        const fury = parseInt((i.potion.match(/data-itemidqty="([0-9]+)" data-name="Recharge the Fury"/i) || [0,0])[1]);
        const spark = parseInt((i.potion.match(/data-itemidqty="([0-9]+)" data-name="Spark the Fury"/i) || [0,0])[1]);
        const elepot = parseInt((i.potion.match(/data-itemidqty="([0-9]+)" data-name="Potion of Elemental Resistance"/i) || [0,0])[1]);
        const kixpot = parseInt((i.potion.match(/data-itemidqty="([0-9]+)" data-name="Kix Potion"/i) || [0,0])[1]);
        const amdirpot = parseInt((i.potion.match(/data-itemidqty="([0-9]+)" data-name="Potion of Amdir"/i) || [0,0])[1]);
        const squidpot = parseInt((i.potion.match(/data-itemidqty="([0-9]+)" data-name="Squidberry Juice"/i) || [0,0])[1]);
        const wonderlandpot = parseInt((i.potion.match(/data-itemidqty="([0-9]+)" data-name="Wonderland Potion"/i) || [0,0])[1]);
        const refills = fury + (spark/2);
        const qitem = parseInt((i.quest.match(regex) || '0').toString().match(/[0-9]+/i));
        const mr = parseInt(i.profile.replace(/,/g,'').match(/Maximum:<\/b><\/td><td>(.*?)<\/td><\/tr>/i)[1]);
        const rpt = parseInt(i.profile.replace(/,/g,'').match(/<p class="top-rage" ONMOUSEOVER="statspopup\(event'<tr><td><b>Per Turn:<\/b><\/td><td>(.*?)<\/td>/i)[1]);
        rows.push(`<tr>
        ${i.static}
        <td class="fury-count">${fury}</td>
        <td class="spark-count">${spark}</td>
        <td>${elepot}</td>
        <td>${kixpot}</td>
        <td>${amdirpot}</td>
        <td>${squidpot}</td>
        <td>${wonderlandpot}</td>
        <td>${qitem}</td>
        <td class="max-rage">${mr.toLocaleString()}</td>
        <td>${rpt.toLocaleString()}</td>
        <td class="projected-qitem">${Math.ceil(runsLeft*(mr+rpt)/20000+qitem)}</td>
        <td width="130px"><input type="text" class="mv-filter fury-math-input" value="${refills}" style="margin-bottom:0px;"></td>
        <td class="fury-math-output">${Math.ceil(refills*mr/20000) + Math.ceil(runsLeft*(mr+rpt)/20000+qitem)}</td>
        </tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div id="banner"></div>
    <div class="mv-table-container"><table class="mv-table sortable">
    <thead>
    <th>char</th>
    <th class="mv-rga-cell">rga</th>
    <th>lvl</th>
    <th><img src="images/rfury.jpg" onmouseover="popup(event,'Recharge the Fury')" onmouseout="kill()"></th>
    <th><img src="images/items/sfury.jpg" onmouseover="popup(event,'Spark the Fury')" onmouseout="kill()"></th>
    <th><img src="images/items/eleresistpotion.png" onmouseover="popup(event,'Potion of Elemental Resistance')" onmouseout="kill()"></th>
    <th><img src="images/potion28.jpg" onmouseover="popup(event,'Kix Potion')" onmouseout="kill()"></th>
    <th><img src="images/items/arelepot.jpg" onmouseover="popup(event,'Potion of Amdir')" onmouseout="kill()"></th>
    <th><img src="images/items/Item_SquidberryJuice.jpg" onmouseover="popup(event,'Squidberry Juice')" onmouseout="kill()"></th>
    <th><img src="images/items/itemz95.png" onmouseover="popup(event,'Wonderland Potion')" onmouseout="kill()"></th>
    <th><img src="${qItemImg}" onmouseover="popup(event,'${qItemLong}')" onmouseout="kill()"></th>
    <th>max rage</th>
    <th>rpt</th>
    <th>proj tot ${qItemShort}</th>
    <th>furys to use</th>
    <th>new proj ${qItemShort}</th>
    </thead>
    <tbody>${rows.join('')}</tbody>
    </table></div>
    `

    const furyInput = Array.from(document.querySelectorAll(".fury-math-input"));
    for (let i = 0; i < furyInput.length; i++) {
        furyInput[i].addEventListener('input',async function(){
            const cellInput = parseFloat(this.value);
            const cellOutput = this.parentNode.parentNode.querySelector('.fury-math-output');
            const cellMaxRage = parseInt(this.parentNode.parentNode.querySelector('.max-rage').innerHTML.replace(/,/g,''));
            const cellQItem = parseInt(this.parentNode.parentNode.querySelector('.projected-qitem').innerHTML.replace(/,/g,''));
            cellOutput.innerHTML = Math.ceil(((cellInput*cellMaxRage)/20000) + cellQItem);
        });
    };

    await sortableTables();
    if (!string.match('Full')){ await mvNotSpecial(event) };
    document.querySelector("#loadingDiv").remove();
};

async function mvHolidays(rgas,string){
    if (!string.match('Full')){ rgas = rgas.slice(0, 2) };
    const endpoints = ['profile','ajax/backpackcontents.php?tab=quest'];
    const array = await mvFetch(rgas,endpoints);
    const rows = [];
    const table = async (i) => {
        const mr = i.profile.match(/Maximum:<\/b><\/td><td>(.*?)<\/td><\/tr>/i)[1];
        const rpt = i.profile.match(/<p class="top-rage" ONMOUSEOVER="statspopup\(event,'<tr><td><b>Per Turn:<\/b><\/td><td>(.*?)<\/td>/i)[1];
        const components = parseInt((i.quest.match(/data-itemidqty="([0-9]+)" data-name="Server Components"/i) || [0,0])[1]);
        const canes = parseInt((i.quest.match(/data-itemidqty="([0-9]+)" data-name="Candy Cane"/i) || [0,0])[1]);
        rows.push(`
        <tr>
        ${i.static}
        <td>${mr}</td>
        <td>${rpt}</td>
        <td>${components}</td>
        <td>${canes}</td>
        </tr>`);
    };
    await Promise.all(array.map(table));
    document.querySelector("#mvContent").innerHTML = `
    <div id="banner"></div>
    <div class="mv-table-container"><table class="mv-table sortable">
    <thead><tr>
    <th>char</th>
    <th class="mv-rga-cell">rga</th>
    <th>lvl</th>
    <th>max rage</th>
    <th>rpt</th>
    <th><img src="images/items/servercomponents.png" onmouseover="popup(event,'Server Components')" onmouseout="kill()"></th>
    <th><img src="images/items/XmasCandyCane2013.jpg" onmouseover="popup(event,'Candy Cane')" onmouseout="kill()"></th>
    </tr></thead>
    <tbody>${rows.join('')}</tbody>
    </table>
    </div>
    `
    await sortableTables();
    if (!string.match('Full')){ await mvNotSpecial("HOLIDAYS") };
    document.querySelector("#loadingDiv").remove();
}



async function mvFetch(rgas,endpoints){

    const loadingDiv = document.createElement("div");
    loadingDiv.innerHTML = `loading<br><span class="blink">&#x29D6;</span>`
    loadingDiv.id = "loadingDiv"
    document.body.appendChild(loadingDiv);

    const array = [];

    const fetch = async (endpoint) => {
        for (let i = 0; i < rgas.length; i++) {

            const key = endpoint.match(/[a-zA-Z]{2,}(?![a-zA-Z])/g)?.pop();

            const login = rgas[i][0]

            const url = endpoint.match(/\?/i) ? endpoint.replace(/\?/i,`?${login}&`) : `${endpoint}?${login}`

            const data = await superfetch(`${url}`);

            if (!array[i]) { array[i] = {} };

            if (!array[i].static) { array[i].static = `<td><a href="profile?${rgas[i][0]}" target="_blank">${rgas[i][3]}</a></td><td class="mv-rga-cell">${rgas[i][1]}</td><td>${rgas[i][4]}</td>`}

            array[i][key] = data;
        };
    };
    await Promise.all(endpoints.map(fetch));
    return array;
};

async function mvItemSpec(itemid){
    const item = (await superfetch(`item_rollover.php?id=${itemid}`)).replace(/<span style="color:#00FF00"> \(\+[0-9]+\)<\/span>/g,'').replace(/<span style="color:#[A-Za-z0-9]+">/g,'').replace(/,|%/g,'');
    const slot = (item.match(/\[Slot - (.*?)\]<br\/>/i) || ['','slot unknown'])[1].toLowerCase();
    const img = itemid > 0 ? `<td><img src="${(item.match(/<img src="([^"]*)" style="border:1px solid #666666;margin:2px;">/i) || ['',''])[1]}" onmouseover="itempopup(event,'${itemid}')" onmouseout="kill()"></img></td>` : '<td></td>';
    const name = '<td style="max-width:200px">' + (item.match(/>(.*?)<\/td><\/tr>/i) || ['',''])[1].replace('td colspan="2"','a')+'</td>';
    const cloned = item.match(/\[Cloned: .*?\]/i) ? true : false;
    const augs = '<td style="max-width:75px">' + (item.match(/src="[^"]*" ONMOUSEOVER="itempopup\(event'[0-9]+_[0-9]+'\)"/g) || []).map(i => `<img ${i.replace('(event','(event,')} onmouseout="kill()" class="mv-augs">`).join('') + '</td>';
    const openaugs = item.match(/\/images\/augslot\.jpg/) ? item.match(/\/images\/augslot\.jpg/g).length : 0;
    const gems = '<td>' +(4-((item.match(/src="\/images\/gemslot2\.jpg"/g) || []).length)) + '</td>';
    const atk = '<td>' + parseInt((item.match(/\+([0-9]+) ATK<br>/i) || [0,0])[1]).toLocaleString() + '</td>';
    const hp = '<td>' + parseInt((item.match(/\+([0-9]+) HP<br>/i) || [0,0])[1]).toLocaleString() + '</td>';
    const ele1 = parseInt((item.match(/\+([0-9]+) Holy<\/span>/i) || [0,0])[1]);
    const ele2 = parseInt((item.match(/\+([0-9]+) Arcane<\/span>/i) || [0,0])[1]);
    const ele3 = parseInt((item.match(/\+([0-9]+) Shadow<\/span>/i) || [0,0])[1]);
    const ele4 = parseInt((item.match(/\+([0-9]+) Fire<\/span>/i) || [0,0])[1]);
    const ele5 = parseInt((item.match(/\+([0-9]+) Kinetic<\/span>/i) || [0,0])[1]);
    const elemental = '<td>' + (ele1 + ele2 + ele3 + ele4 + ele5).toLocaleString() + '</td>';;
    const ele6 = '<td>' + parseInt((item.match(/\+([0-9]+) Chaos<\/span>/i) || [0,0])[1]).toLocaleString() + '</td>';
    const res1 = parseInt((item.match(/\+([0-9]+) Holy Resist/i) || [0,0])[1]);
    const res2 = parseInt((item.match(/\+([0-9]+) Arcane Resist/i) || [0,0])[1]);
    const res3 = parseInt((item.match(/\+([0-9]+) Shadow Resist/i) || [0,0])[1]);
    const res4 = parseInt((item.match(/\+([0-9]+) Fire Resist/i) || [0,0])[1]);
    const res5 = parseInt((item.match(/\+([0-9]+) Kinetic Resist/i) || [0,0])[1]);
    const resist = '<td>' + (res1 + res2 + res3 + res4 + res5).toLocaleString() + '</td>';;
    const res6 = '<td>' + (item.match(/\+([0-9]+) Chaos Resist/i) || [0,0])[1] + '</td>';
    const vile = '<td>' + parseInt((item.match(/\+([0-9]+) vile energy/i) || [0,0])[1]).toLocaleString() + '</td>';
    const rpt = '<td>' + parseInt((item.match(/\+([0-9]+) rage per hr/i) || [0,0])[1]).toLocaleString() + '</td>';
    const ept = '<td>' + parseInt((item.match(/\+([0-9]+) exp per hr/i) || [0,0])[1]).toLocaleString() + '</td>';
    const rampage = '<td>' + (item.match(/\+([0-9]+) rampage/i) || [0,0])[1] + '</td>';
    const critical = '<td>' + (item.match(/\+([0-9]+) critical hit/i) || [0,0])[1] + '</td>';
    const mr = '<td>' + parseInt((item.match(/\+([0-9]+) max rage/i) || [0,0])[1]).toLocaleString() + '</td>';
    const block = '<td>' + (item.match(/\+([0-9]+) block/i) || [0,0])[1] + '</td>';
    const eleblock = '<td>' + (item.match(/\+([0-9]+) elemental block/i) || [0,0])[1] + '</td>';
    const ps = '<td>' + (item.match(/\+(\d+(\.\d+)?) perfect strike/i) || [0,0])[1] + '</td>';;
    return {slot:slot,img:img,name:name,cloned:cloned,augs:augs,openaugs:openaugs,gems:gems,atk:atk,hp:hp,elemental:elemental,ele6:ele6,resist:resist,res6:res6,vile:vile,rpt:rpt,ept:ept,rampage:rampage,critical:critical,mr:mr,block:block,eleblock:eleblock,ps:ps};
};

async function mvNotSpecial(tab){
    document.querySelector("#banner").innerHTML = `
    <div style="background:#870000;width:100%;height:80px;text-align:center;justify-content:center;align-items:center;display:flex;margin-bottom:1rem;">
    <a href="https://www.patreon.com/moxximod" target="_blank" class="mv-btn" style="width:400px;padding:4px 8px;">PLEASE SUBSCRIBE TO MOXXIMOD+ TO UNLOCK THE ${tab} TAB</a>
    </div>
    `
};


async function openPotionBp(){
    window.XMLHttpRequest.prototype.realOpen = window.XMLHttpRequest.prototype.open;
    window.XMLHttpRequest.prototype.open = function(method, url) {
        if (url.includes('ajax/backpackcontents.php?tab=potion')) {
            this.onreadystatechange = function() {
                if (this.readyState === 4) {
                    var pbp = this.responseText;
                    const inbp = pbp.replace(/'/g,'').match(/data-name="[^"]*"/g).map(pot => pot.match(/"([^"]*)"/i)[1]);
                    info("All Potions").then(array => {
                        const allpots = array.map(([item]) => item);
                        const missing = allpots.filter(item => !inbp.includes(item) && item != "Boost One" && item != "Boost Two" && item != "Boost Three" && item != "Boost Four" && item != "Boost Five");
                        if (GM_getValue('auth').match('Full')){
                            document.querySelector("#backpackitemct").innerHTML = `missing<img src="https://studiomoxxi.com/moxximod/toolbarbot.png" height="20px" width="20px" onmouseover="statspopup(event,'<font color=#FFFFFF><b>POTIONS NOT IN BACKPACK</b><br>${missing.join('<br>')}')" onmouseout="kill()">`
                        } else {
                            document.querySelector("#backpackitemct").innerHTML = `missing<img src="https://studiomoxxi.com/moxximod/toolbarbot.png" height="20px" width="20px" onmouseover="statspopup(event,'<font color=#FFFFFF>Please subscribe to MoxxiMod+ to see missing potions')" onmouseout="kill()">`
                        };
                    });
                };
            };
        };
        this.realOpen.apply(this, arguments);
    };
};


async function blankOverlay(server,serverNo,rgaName,charId){

    appsMenuClose();

    $("body").append(`
    <div id="blankOverlay">
    <a href="https://${server}.outwar.com/home?rg_sess_id=${rgaName}&suid=${charId}&serverid=${serverNo}">CLOSE</a>
    <div class="widget" style="width:80%;height:90%;left:10%;right:10%;box-shadow: 0 6px 10px 0 rgba(0,0,0,1),0 1px 18px 0 rgba(0,0,0,1),0 3px 5px -1px rgba(0,0,0,.2);" id="overlayWidget">
    </div>
    </div>`);

    document.body.style.overflow = 'hidden';

    document.querySelector("#blankOverlay").setAttribute('style',`background:#000000;padding:20px;`)
};


async function parseAugments(){
    const tip = document.getElementById('dhtmltooltip');

    const observerCallback = async () => {
        if (tip.innerHTML.match(/id="itemtable"/i)) {

            observer.disconnect();

            await parse(tip);

            await parseAugments();
        };
    };
    const observer = new MutationObserver(observerCallback);
    observer.observe(tip, { attributes: true, childList: true, subtree: true });

    async function parse(tip){
        let itemHoly = parseInt((tip.innerHTML.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Holy/i) || [0,0])[1]);
        let itemArcane = parseInt((tip.innerHTML.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Arcane/i) || [0,0])[1]);
        let itemShadow = parseInt((tip.innerHTML.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Shadow/i) || [0,0])[1]);
        let itemFire = parseInt((tip.innerHTML.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Fire/i) || [0,0])[1]);
        let itemKinetic = parseInt((tip.innerHTML.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Kinetic/i) || [0,0])[1]);
        let itemChaos = parseInt((tip.innerHTML.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Chaos/i) || [0,0])[1]);
        let itemHolyRes = parseInt((tip.innerHTML.replace(/,/g,'').match(/\+([0-9]+) Holy Resist/i) || [0,0])[1]);
        let itemArcaneRes = parseInt((tip.innerHTML.replace(/,/g,'').match(/\+([0-9]+) Arcane Resist/i) || [0,0])[1]);
        let itemShadowRes = parseInt((tip.innerHTML.replace(/,/g,'').match(/\+([0-9]+) Shadow Resist/i) || [0,0])[1]);
        let itemFireRes = parseInt((tip.innerHTML.replace(/,/g,'').match(/\+([0-9]+) Fire Resist/i) || [0,0])[1]);
        let itemKineticRes = parseInt((tip.innerHTML.replace(/,/g,'').match(/\+([0-9]+) Kinetic Resist/i) || [0,0])[1]);
        let augsHoly = 0
        let augsArcane = 0
        let augsShadow = 0
        let augsFire = 0
        let augsKinetic = 0
        let augsChaos = 0
        let augsHolyRes = 0
        let augsArcaneRes = 0
        let augsShadowRes = 0
        let augsFireRes = 0
        let augsKineticRes = 0
        const allAugs = tip.innerHTML.match(/[0-9]+_[0-9]+/g) || []

        const augs = async (iid) => {
            const aug = await superfetch(`item_rollover.php?id=${iid}`);

            itemHoly -= parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Holy/i) || [0,0])[1]);
            augsHoly += parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Holy/i) || [0,0])[1]);
            itemHolyRes -= parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) Holy Resist/i) || [0,0])[1]);
            augsHolyRes += parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) Holy Resist/i) || [0,0])[1]);

            itemArcane -= parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Arcane/i) || [0,0])[1]);
            augsArcane += parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Arcane/i) || [0,0])[1]);
            itemArcaneRes -= parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) Arcane Resist/i) || [0,0])[1]);
            augsArcaneRes += parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) Arcane Resist/i) || [0,0])[1]);

            itemShadow -= parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Shadow/i) || [0,0])[1]);
            augsShadow += parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Shadow/i) || [0,0])[1]);
            itemShadowRes -= parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) Shadow Resist/i) || [0,0])[1]);
            augsShadowRes += parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) Shadow Resist/i) || [0,0])[1]);

            itemFire -= parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Fire/i) || [0,0])[1]);
            augsFire += parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Fire/i) || [0,0])[1]);
            itemFireRes -= parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) Fire Resist/i) || [0,0])[1]);
            augsFireRes += parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) Fire Resist/i) || [0,0])[1]);

            itemKinetic -= parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Kinetic/i) || [0,0])[1]);
            augsKinetic += parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Kinetic/i) || [0,0])[1]);
            itemKineticRes -= parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) Kinetic Resist/i) || [0,0])[1]);
            augsKineticRes += parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) Kinetic Resist/i) || [0,0])[1]);

            itemChaos -= parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Chaos/i) || [0,0])[1]);
            augsChaos += parseInt((aug.replace(/,/g,'').match(/\+([0-9]+) <span style="[^"]*">Chaos/i) || [0,0])[1]);
        };
        await Promise.all(allAugs.map(augs));
        tip.innerHTML = tip.innerHTML.replace(/,/g,'')
        if (augsHoly > 0){ tip.innerHTML = tip.innerHTML.replace(/\+([0-9]+) <span style="[^"]*">Holy/i,`+${itemHoly.toLocaleString()} <font color="#00FF00">(+${augsHoly.toLocaleString()})</font> Holy`) }
        if (augsHolyRes > 0){ tip.innerHTML = tip.innerHTML.replace(/\+([0-9]+) Holy Resist/i,`+${itemHolyRes.toLocaleString()} <font color="#00FF00">(+${augsHolyRes.toLocaleString()})</font> Holy Resist`) }
        if (augsArcane > 0){ tip.innerHTML = tip.innerHTML.replace(/\+([0-9]+) <span style="[^"]*">Arcane/i,`+${itemArcane.toLocaleString()} <font color="#00FF00">(+${augsArcane.toLocaleString()})</font> Arcane`) }
        if (augsArcaneRes > 0){ tip.innerHTML = tip.innerHTML.replace(/\+([0-9]+) Arcane Resist/i,`+${itemArcaneRes.toLocaleString()} <font color="#00FF00">(+${augsArcaneRes.toLocaleString()})</font> Arcane Resist`) }
        if (augsShadow > 0){ tip.innerHTML = tip.innerHTML.replace(/\+([0-9]+) <span style="[^"]*">Shadow/i,`+${itemShadow.toLocaleString()} <font color="#00FF00">(+${augsShadow.toLocaleString()})</font> Shadow`) }
        if (augsShadowRes > 0){ tip.innerHTML = tip.innerHTML.replace(/\+([0-9]+) Shadow Resist/i,`+${itemShadowRes.toLocaleString()} <font color="#00FF00">(+${augsShadowRes.toLocaleString()})</font> Shadow Resist`) }
        if (augsFire > 0){ tip.innerHTML = tip.innerHTML.replace(/\+([0-9]+) <span style="[^"]*">Fire/i,`+${itemFire.toLocaleString()} <font color="#00FF00">(+${augsFire.toLocaleString()})</font> Fire`) }
        if (augsFireRes > 0){ tip.innerHTML = tip.innerHTML.replace(/\+([0-9]+) Fire Resist/i,`+${itemFireRes.toLocaleString()} <font color="#00FF00">(+${augsFireRes.toLocaleString()})</font> Fire Resist`) }
        if (augsKinetic > 0){ tip.innerHTML = tip.innerHTML.replace(/\+([0-9]+) <span style="[^"]*">Kinetic/i,`+${itemKinetic.toLocaleString()} <font color="#00FF00">(+${augsKinetic.toLocaleString()})</font> Kinetic`) }
        if (augsKineticRes > 0){ tip.innerHTML = tip.innerHTML.replace(/\+([0-9]+) Kinetic Resist/i,`+${itemKineticRes.toLocaleString()} <font color="#00FF00">(+${augsKineticRes.toLocaleString()})</font> Kinetic Resist`) }
        if (augsChaos > 0){ tip.innerHTML = tip.innerHTML.replace(/\+([0-9]+) <span style="[^"]*">Chaos/i,`+${itemChaos.toLocaleString()} <font color="#00FF00">(+${augsChaos.toLocaleString()})</font> Chaos`) }
    };
};

async function blankOff(){
    GM_addStyle(`
        @keyframes fadeOut {from {opacity: 1;} to {opacity: 0;}}
        #blankOverlay {animation: fadeOut 1s ease;}
    `)
    await new Promise(resolve => setTimeout(resolve, 1000));
    document.querySelector("#blankOverlay").remove();
    document.body.style.overflowY = 'visible';
};


async function loadingOverlay(){

    $("body").append(`
    <div id="loadingOverlay">
    <img src="https://studiomoxxi.com/moxximod/loading-gif.gif">
    </div>`);

    document.body.style.overflow = 'hidden';

    document.querySelector("#loadingOverlay").setAttribute('style',`background:#000000;padding:20px;`)
};

async function loadingOff(){
    document.body.style.overflowY = 'visible';
    document.querySelector("#loadingOverlay").remove();
};


async function info(request){

    if (request == 'Array of all gods'){
        return ["Animation of Versatility", "Ag Nabak the Abomination", "Agnar, Astral Betrayer", "Akkel the Enflamed Warrior", "Amalgamated Apparition", "Ancient Magus Tarkin", "Anguish", "Animated Captain", "Anvilfist", "Archdevil Yirkon", "Arcon, the Arcane Deity", "Balerion, Dragon of Dread", "Banok, Demon of Insanity", "Baron Mu, Dark Rider of the Undead", "Beast of Cards", "Bloodchill the Grizzly", "Bolkor, the Holy Master", "Brutalitar, Lord of the Underworld", "Crane", "Crantos, Defender of Ultimation", "Crolvak, the Fire Master", "Detox", "Dexor, Victor of Veldara", "Dlanod, the Crazed Chancellor", "Dreg nor, Keeper of the Infernal Essence", "Ebliss, Fallen Angel of Despair", "Emperor Neudeus, Controller of the Universe", "Envar, Demon of Lunacy", "Esquin, the Kinetic Master", "Felroc, Overseer of Hellfire", "Firan, the Fire Deity", "Freezebreed, The Frozen Manipulator", "Ganja the Stone Golem", "Garland, The Lord Keeper", "Gnorb", "Gorganus of the Wood", "Great Lord Ganeshan", "Gregov, Knight of the Woods", "Grivvek, Protector of the Brood", "Hackerphage, Protector of the Gateway", "Holgor, the Holy Deity", "Howldroid, Tormentor of the Pit", "Hyrak, Bringer of Nightmares", "Jade Dragonite", "Jazzmin, Maiden of Vitality", "Jorun the Blazing Swordsman", "Karvaz, Lord of Alsayic", "Keeper of Nature", "Kinark, the Kinetic Deity", "King Ashnar, Lord of the Unliving", "Kretok, Descendant of Nature", "Kro Shuk, Doomslayer", "Lacuste of the Swarm", "Lady Ariella", "Lady Chaos, Queen of the Abyss", "Lord Narada", "Lord Sibannac", "Lord Suka", "Lord Varan", "Lord Xordam", "Melt Bane, The Forbidden Demon Dragon", "Mistress of the Sword", "Murderface", "Murfax, Beast of the Caves", "Nafir, God of Desolation", "Nar Zhul, Slayer of All", "Nayark the Mummified Sorcerer", "Nessam", "Noxious Slug", "Numerocure, The Black Messenger of Evil", "Old World Drake", "Ormsul the Putrid", "Pinosis", "Q-SEC Commander", "Quiver, The Renegade", "Raiyar, the Shadow Master", "Rancid, Lord of Thugs", "Rezun, Demon of Madness", "Rillax, Twin of Wisdom", "Rotborn, Eater of the Dead", "Samatha Dark-Soul", "Sarcrina the Astral Priestess", "Shadow", "Shayar, the Shadow Deity", "Sigil, Lich of Woe", "Skarthul the Avenged", "Skybrine The Inescapable", "Slashbrood, Devourer of the Blackness", "Smoot the Yeti", "Straya, the Underworld Ruler", "Sylvanna TorLai", "Synge, The Red Dragon", "Terrance, Rebel of Rallis", "Thanox, Balancer of Chaos", "The Emerald Assassin", "Threk, King of Lords", "Traxodon the Plaguebringer", "Tsort", "Tylos, The Lord Master", "Valzek, Harbinger of Death", "Varsanor, Master of Darkness", "Villax, Twin of Strength", "Viserion, the Necrodragon", "Vitkros, Hydra of the Deep", "Volgan the Living Ironbark", "Wanhiroeaz the Devourer", "Windstrike The Vile", "Xynak, the Arcane Master", "Zertan, The Collector", "Zikkir the Dark Archer"];

    } else if (request == 'Cosmos, Great All Being'){
        return [100000000000,50,'Demonic Teleporter<br>Recharge the Fury<br>Cosmos Talisman<br>Tome of Daily Grind<br>Key to Knights Horror<br>Astral Shard<br>Quest Shard<br>Recharge Totem<br>Star Power<br>Ticket to the Mystifying Carnival<br>Containment Orb<br>Orb of the Scepter<br>Amulet Chest (50)']

    } else if (request == 'Death, Reaper of Souls'){
        return [290000000000,80,'Recharge Totem<br>Recharge the Fury<br>Standard Issue Neuralyzer<br>Death Talisman<br>Pirate Treasure Map<br>Key of the Elements<br>Advanced Neuralyzer<br>Trinket Items<br>Elemental Vigor Orb<br>Elemental Assault Orb<br>Elemental Defense Orb<br>Amulet Chest (50)<br>Chancellor Items<br>Spiral Gear']

    } else if (request == 'Maekrix, Dreaded Striker'){
        return [320000000000,73,'Red Dragon Items<br>Astral Totem<br>Maekrix Talisman<br>Key to the Alsayic Ruins (Solo)<br>Juggernaut Talisman<br>Advanced Neuralyzer<br>Irthys Vigor Orb<br>Irthys Assault Orb<br>Irthys Defense Orb<br>Add Augment Slot<br>Remove Augment<br>Amulet Chest (50)<br>Nobel Gear']

    } else if (request == 'Blackhand Reborn'){
        return [570000000000,61,'Augment of the Reborn Knight<br>Core of Blackhand<br>Essence of Reincarnation<br>Blackhand Talisman<br>Profound Ward<br>8-Bit Banana<br>Buckler of Insanity<br>Hauberk of Lunacy<br>Charm of Havoc<br>Unstoppable Concoction<br>Advanced Neuralyzer<br>Power Potion Pack<br>Flask of Endurance<br>Magic Gem<br>Thunder Ball<br>Perfection Gear<br>Exalted Gear']

    } else if (request == 'Zyrak, Vision of Madness'){
        return [1200000000000,65,'Augment of Madness<br>Unstable Jewel<br>Veldarabloom<br>Scripture of Zyrak<br>Pulsating Stone<br>Bottled Chaos<br>Thunder Ball<br>Force of Veldara<br>Interstellar Vessel<br>Vault Tear<br>Vial of Insanity<br>Demonic Madness<br>Infinite Tower Spheroid<br>Transcended Extract<br>Tier 2 Booster Upgrade<br>Ghostly Gear<br>Boon of Vision<br>Ancestral Tombs']

    } else if (request == 'Triworld Simulation'){
        return [2400000000000,39,'20x Ask The Oracle Bundle<br>20x Remove Augment Bundle<br>Augment of Simulation<br>Cosmic Mote<br>Amalgamation Blossoms<br>Catalysts of Addumulation<br>Faction Change<br>Codex Chapter 30<br>Codex Chapter 31<br>Triworld Experience Ward<br>Descendant Set Items<br>Quest Experience Potion<br>Blazing Serpent Gear']

    } else if (request == 'Arkron, God of Trials'){
        return [900000000000,160,'']

    } else if (request == 'Bazak, Demon of Hatred'){
        [900000000000,160,'']

    } else if (request == 'Vorox, Mind of Ruin'){
        return [900000000000,160,'']
    } else if (request == 'All Potions'){
        return [
            [`Triworld Tincture`,`/images/items/triworldtincture.png`],
            [`20 Year Aged Whiskey`,`/images/items/whiskeypot.png`],
            [`Blazing Holiday Sauce`,`/images/items/emblemPotion2.jpg`],
            [`Bottle of Holy Slaughter`,`/images/potion26.jpg`],
            [`Brew of Precision`,`/images/items/potion3.gif`],
            [`Holy Vile`,`/images/items/Pot_HolyVile.jpg`],
            [`Damned Element Shot`,`/images/items/h16_Pot6.png`],
            [`Demonic Madness`,`/images/items/vaultpot2.png`],
            [`Dose of Destruction`,`/images/pot2.jpg`],
            [`Evil Scream`,`/images/potion25.jpg`],
            [`Fire Water`,`/images/potion22.jpg`],
            [`Flask of Burning Souls`,`/images/items/basicflask1.gif`],
            [`Flask of Conjured Lightning`,`/images/basicflask4.gif`],
            [`Flask of Endurance`,`/images/items/itemz28.jpg`],
            [`Flask of Flaming Death`,`/images/basicflask2.gif`],
            [`Flask of Forbidden Knowledge`,`/images/basicflask3.gif`],
            [`Flask of Super Nova`,`/images/basicflask5.gif`],
            [`Funny Little Mushroom`,`/images/mushroom.jpg`],
            [`Griznix Potion`,`/images/items/purepwnagepotion.png`],
            [`Halloween Potion`,`/images/items/itemz27.jpg`],
            [`Jabberwocky Blood`,`/images/items/Item_JabberwockyBlood.jpg`],
            [`Kinetic Potency`,`/images/items/KineticShot.jpg`],
            [`Kix Potion`,`/images/potion28.jpg`],
            [`Kombucha`,`/images/items/Putrid%20Power%20Clusters.jpg`],
            [`Liquid Bone Juice`,`/images/items/Item_JabberwockyBlood.jpg`],
            [`Major Chaos Philter`,`/images/items/itemz82.jpg`],
            [`Marsh Water`,`/images/potion24.jpg`],
            [`Minor Chaos Philter`,`/images/items/itemz91.jpg`],
            [`Olympian Juicebox`,`/images/items/lesserolympian.png`],
            [`Olympian Push`,`/images/items/2k8.png`],
            [`Potion of Amdir`,`/images/items/arelepot.jpg`],
            [`Potion of Deceit`,`/images/items/potion2.gif`],
            [`Potion of Elemental Resistance`,`/images/items/eleresistpotion.png`],
            [`Potion of Enraged Alsayic`,`/images/items/PotionofEA.jpg`],
            [`Pumpkin Juice`,`/images/halloween/PumpkinJuice.gif`],
            [`Quantum Quattro`,`/images/items/pot_quantumquattro.jpg`],
            [`Rampage Vile`,`/images/items/Pot_RampageVile.jpg`],
            [`Reikavons Elixir`,`/images/items/ReikavonsElixer.jpg`],
            [`Remnant Solice Lev 10`,`/images/items/90remnant.png`],
            [`Remnant Solice Lev 11`,`/images/items/95remnant.png`],
            [`Sammy Sosas Special Sauce`,`/images/pot5.jpg`],
            [`Squidberry Juice`,`/images/items/Item_SquidberryJuice.jpg`],
            [`Star Power`,`/images/items/starpowerelec.jpg`],
            [`Strong Man Elixir`,`/images/items/potion1.gif`],
            [`Sugar Daddy`,`/images/items/sugardaddy.png`],
            [`Unstoppable Concoction`,`/images/items/juggerelepot.jpg`],
            [`Vial of Insanity`,`/images/items/vaultpot1.png`],
            [`Vile Energy`,`/images/items/vile_energy_potion.jpg`],
            [`Wonderland Potion`,`/images/items/itemz95.png`],
            [`Zhulian Potion`,`/images/items/wozpotionzor.jpg`],
            [`Zombie Potion 1`,`/images/items/potion_1.gif`],
            [`Zombie Potion 2`,`/images/items/potion_2.gif`],
            [`Zombie Potion 3`,`/images/items/potion_3.gif`],
            [`Zombie Potion 4`,`/images/items/potion_4.gif`],
            [`Zombie Potion 5`,`/images/items/potion_5.gif`],
            [`Zombie Potion 6`,`/images/items/potion_6.gif`],
            [`Boost One`,`/images/items/icon_vial_blue.jpg`],
            [`Boost Two`,`/images/items/icon_vial_green.jpg`],
            [`Boost Three`,`/images/items/icon_vial_orange.jpg`],
            [`Boost Four`,`/images/items/icon_vial_red.jpg`],
            [`Boost Five`,`/images/items/icon_vial_yellow.jpg`]
        ]
    } else if (request = "Cost to Gem"){
        return {
            "cccccc":[10,9,7,4,0],
            "FFFFFF":[25,23,18,10,0],
            "1eff00":[50,45,35,20,0],
            "ffde5b":[100,90,70,40,0],
            "CA1111":[200,180,140,80,0],
            "0070ff":[300,270,210,120,0],
            "ff8000":[400,360,280,160,0],
            "9000ba":[500,450,350,200,0]
        };
    } else {
        return 'error';
    };
};


async function superfetch(url,skipCache){
    if (!skipCache && superfetchCache.hasOwnProperty(url)) {
        return superfetchCache[url];
    } else {
        while (true) {
            try {
                let data = await fetch(url).then(res => res.text());
                if (data.match(/"error":"Rate limit exceeded/i)){
                    await new Promise(resolve => setTimeout(resolve, 1000));
                } else {

                    superfetchCache[url] = data;

                    if (data.match('images/ErrorImg.jpg')){
                        data = "error"
                    };

                    return data;
                };
            } catch (error) {
                await new Promise(resolve => setTimeout(resolve, 1000));
            };
        };
    };
};


async function superpost(url,body){
    while (true) {
        try {
            const response = await fetch(url, {
                method: 'POST',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                body: body
            });

            const data = await response.text();

            if (data.includes("Rate limit exceeded. Please be kind to our servers ;)")) {
                await new Promise(resolve => setTimeout(resolve, 1000));
            } else {
                return data;
            }
        } catch (error) {
            await new Promise(resolve => setTimeout(resolve, 1000));
        };
    };
};


async function updateRga(rgaName){
    if (rgaName != GM_getValue("rgaName")){
        await mmplus(`AuthCheck|${rgaName}`);
        await GM_setValue("rgaName",rgaName);
    };
};


function mmplus(string) {
    return new Promise((resolve) => {
        let rgaName;
        if (document.querySelector("#rg_sess_id")) {
            rgaName = document.querySelector("#rg_sess_id").value;
        } else {
            rgaName = document.body.innerHTML.match(/rg_sess_id=([A-Za-z0-9]+)">[\n\r]<img src="\/assets\/img\/getpoints\.webp">/i)[1];
        };
        const task = string.replace('rganame',rgaName);
        GM_xmlhttpRequest({
            method: 'POST',
            url: 'http://boss.outwar.link:8001/',
            data: task,
            headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
            onload: function(data) {
                const response = data.response;
                if (response.match(/^[a-zA-Z]+$/)){
                    GM_setValue("auth", response);
                };
                displayAuthStatus(response).then(() => {
                    resolve(response);
                });
            }
        });
    });
}


async function displayAuthStatus(status) {
    const moxxiImg = '<img src="https://studiomoxxi.com/moxximod/toolbarbot.png" style="height:25px;width:25px;margin-right:5px;margin-bottom:3px;">'
    if (authSliderCreated == false) {
        var newDiv = document.createElement('div');
        newDiv.id = 'authSlider';
        document.body.appendChild(newDiv);
    };
    if (status.match("NotAuthed")) {
        document.querySelector("#authSlider").innerHTML = `${moxxiImg} THIS RGA IS NOT SUBSCRIBED TO MOXXIMOD+`;
        document.querySelector("#authSlider").setAttribute('style', 'background:#870000;');
    } else {
        document.querySelector("#authSlider").innerHTML = `${moxxiImg} THANK YOU FOR SUBSCRIBING TO MOXXIMOD+`;
        document.querySelector("#authSlider").setAttribute('style', 'background:#008700;');
    };

    GM_addStyle("#authSlider {animation: none;}");

    document.querySelector("#authSlider").offsetHeight;

    GM_addStyle("#authSlider {animation: authSliderAnimation 3s ease forwards;}");
    GM_addStyle("@keyframes authSliderAnimation {0% {height:0px;position:fixed;bottom:-45px;opacity:0;} 50% {height:45px;position:fixed;bottom:0px;opacity:1:padding:10px} 80% {height:45px;position:fixed;bottom:0px;opacity:1;padding:10px} 100% {height:0px;position:fixed;bottom:-45px;opacity:0}}");
    authSliderCreated = true;
};

async function filterTables() {

    const filterInput = document.getElementById('filter');
    const tableRows = document.querySelectorAll('.filterable tbody tr');
    filterInput.addEventListener('input', function() {
        const filterValue = this.value.trim().toLowerCase();
        tableRows.forEach(row => {
            const cells = row.querySelectorAll('.filt');
            let matched = false;
            cells.forEach(cell => {
                const values = cell.textContent.split(',').map(item => item.trim().toLowerCase());
                if (values.includes(filterValue)) {
                    matched = true;
                };
            });
            if (filterValue === '' || matched) {
                row.style.display = '';
            } else {
                row.style.display = 'none';
            };
        });
    });
};

async function sortableTables() {

    document.querySelectorAll('table.sortable').forEach(table => {
        Array.from(table.querySelectorAll('thead th')).forEach(header => {
            header.addEventListener('click', event => {
                const columnIndex = header.cellIndex;
                const tbody = table.querySelector('tbody');
                const rows = Array.from(tbody.querySelectorAll('tr'));
                const isAscending = header.classList.contains('ascending');
                rows.sort((a, b) => {
                    const aValue = getValue(a.cells[columnIndex].textContent);
                    const bValue = getValue(b.cells[columnIndex].textContent);
                    if (typeof aValue === 'number' && typeof bValue === 'number') {
                        return isAscending ? aValue - bValue : bValue - aValue;
                    } else {
                        if (isAscending) {
                            return aValue.localeCompare(bValue);
                        } else {
                            return bValue.localeCompare(aValue);
                        };
                    };
                });
                header.classList.toggle('ascending', !isAscending);
                header.classList.toggle('descending', isAscending);
                rows.forEach(row => tbody.removeChild(row));
                rows.forEach(row => tbody.appendChild(row));
            });
            header.style.cursor = 'pointer';
        });
    });
    function getValue(value) {
        const parsedValue = parseFormattedNumber(value);
        return isNaN(parsedValue) ? value.trim() : parsedValue;
    };
    function parseFormattedNumber(value) {
        return parseInt(value.replace(/,/g, ''), 10);
    };
    GM_addStyle(`table.sortable th:after {content: "▾";margin-left: 0.1em;}`)
};