Eternity Tower Quick Sets

Equips skin, gear, and abilities in configurable sets

目前為 2018-08-08 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name          Eternity Tower Quick Sets
// @icon          https://www.eternitytower.net/favicon.png
// @namespace     http://mean.cloud/
// @version       1.11
// @description   Equips skin, gear, and abilities in configurable sets
// @match         http*://*.eternitytower.net/*
// @author        [email protected]
// @copyright     2017-2018, MeanCloud
// @run-at        document-end
// @grant         GM_getValue
// @grant         GM_setValue
// @grant         GM_deleteValue
// ==/UserScript==


////////////////////////////////////////////////////////////////
////////////// ** SCRIPT GLOBAL INITIALIZATION ** //////////////
function startup() { ET_QuickSetsMod(); }
PETQS_EquippedItems = [];
PETQS_EquippedAbilities = [];
PETQS_AllItems = [];
PETQS_PageOn = 1;
PETQS_PageMax = 10;
PETQS_SetsPerPage = 8;
////////////////////////////////////////////////////////////////


ET_QuickSetsMod = function()
{
    //ET.MCMF.WantDebug = true;

    ET.MCMF.Ready(function()
    {
        Package.meteor.Meteor.connection._stream.on('message', function(sMeteorRawData)
        {
            try
            {
                var oMeteorData = JSON.parse(sMeteorRawData);

                //todo: use Package.meteor.global.Accounts.connection._stores.abilities._getCollection()._collection
                try
                {
                    if (oMeteorData.collection == "abilities")
                    {
                        if (oMeteorData.fields && oMeteorData.fields.learntAbilities)
                        {
                            PETQS_EquippedAbilities = [];

                            jQ.makeArray(oMeteorData.fields.learntAbilities).forEach(function(oAbility, index, array)
                             {
                                try
                                {
                                    if (oAbility.equipped)
                                        PETQS_EquippedAbilities.push(oAbility);
                                }
                                catch (err) { console.log("Error with PETQS/ability: " + err); }
                            });
                        }
                    }
                }
                catch (err) { console.log("Error with PETQS/abilities: " + err); }

                //todo: Package.meteor.global.Accounts.connection._stores.items._getCollection()._collection
                try
                {
                    if (oMeteorData.collection == "items")
                    {
                        if (oMeteorData.msg == "added")
                            if (oMeteorData.fields && oMeteorData.fields.itemId && oMeteorData.fields.name && oMeteorData.fields.category)
                                PETQS_AllItems.push(oMeteorData);

                        if (oMeteorData.fields && oMeteorData.fields.equipped)
                        {
                            PETQS_EquippedItems.push(oMeteorData);
                        }
                        else
                        {
                            if (PETQS_EquippedItems.length > 0)
                            {
                                for (i = 0; i < PETQS_EquippedItems.length; i++)
                                {
                                    if (PETQS_EquippedItems[i].id == oMeteorData.id)
                                    {
                                        PETQS_EquippedItems.splice(i, 1);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                catch (err) { console.log("Error with PETQS/items: " + err); }
            }
            catch (err) { console.log("Error with PETQS/meteor: " + err); }
        });
    });

    ET.MCMF.Loaded(function()
    {
        PETQS_PageOn = CInt(GM_getValue("PETQS_Page"));
        if (PETQS_PageOn === 0)
            PETQS_PageOn = 1;
        PETQS_TestUI();
    }, "ETQS");
};

PETQS_TestUI = function()
{
    try
    {
        if (jQ("div#PETQS_UI").length === 0)
            if (jQ("div.hidden-lg-down").length > 0)
                PETQS_CreateUI();
    }
    catch (err) { }

    setTimeout(PETQS_TestUI, 1000);
};

PETQS_CreateUI = function()
{
    jQ("div#PETQS_UI").remove();

    jQ(jQ("div.hidden-lg-down").children("div").get(0)).append
    (
        "<div style=\"margin-top: 20px; border: 1px solid #dde; background-color: #fafbfd; padding: 5px; width: 280px; font-size: 14px;\" id=\"PETQS_UI\">" +
        "<div style=\"width: 270px; max-width: 270px; height: 22px; cursor: pointer;\" id=\"PETQS_Slotbar" + pad(1 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage), 2) + "\" onclick=\"javascript:PETQS_ClickedSet(" + (1 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ",event);\">[empty set]</div>" +
        "<div style=\"width: 270px; max-width: 270px; height: 22px; cursor: pointer;\" id=\"PETQS_Slotbar" + pad(2 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage), 2) + "\" onclick=\"javascript:PETQS_ClickedSet(" + (2 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ",event);\">[empty set]</div>" +
        "<div style=\"width: 270px; max-width: 270px; height: 22px; cursor: pointer;\" id=\"PETQS_Slotbar" + pad(3 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage), 2) + "\" onclick=\"javascript:PETQS_ClickedSet(" + (3 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ",event);\">[empty set]</div>" +
        "<div style=\"width: 270px; max-width: 270px; height: 22px; cursor: pointer; margin-bottom: 4px;\" id=\"PETQS_Slotbar" + pad(4 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage), 2) + "\" onclick=\"javascript:PETQS_ClickedSet(" + (4 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ",event);\">[empty set]</div>" +
        "<div style=\"width: 270px; max-width: 270px; height: 22px; cursor: pointer; border-top: 1px solid #dde;\" id=\"PETQS_Slotbar" + pad(5 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage), 2) + "\" onclick=\"javascript:PETQS_ClickedSet(" + (5 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ",event);\">[empty set]</div>" +
        "<div style=\"width: 270px; max-width: 270px; height: 22px; cursor: pointer;\" id=\"PETQS_Slotbar" + pad(6 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage), 2) + "\" onclick=\"javascript:PETQS_ClickedSet(" + (6 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ",event);\">[empty set]</div>" +
        "<div style=\"width: 270px; max-width: 270px; height: 22px; cursor: pointer;\" id=\"PETQS_Slotbar" + pad(7 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage), 2) + "\" onclick=\"javascript:PETQS_ClickedSet(" + (7 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ",event);\">[empty set]</div>" +
        "<div style=\"width: 270px; max-width: 270px; height: 22px; cursor: pointer;\" id=\"PETQS_Slotbar" + pad(8 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage), 2) + "\" onclick=\"javascript:PETQS_ClickedSet(" + (8 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ",event);\">[empty set]</div>" +
        "<div style=\"width: 270px; max-width: 270px; padding-top: 10px;\">" +
        "<input type=\"button\" value=\"Save #" + (1 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + "\" onclick=\"javascript:PETQS_SaveSet(" + (1 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ");\" style=\"display: inline-block; width: 64px; font-size: 12px;\" /> " +
        "<input type=\"button\" value=\"Save #" + (2 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + "\" onclick=\"javascript:PETQS_SaveSet(" + (2 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ");\" style=\"display: inline-block; width: 64px; font-size: 12px;\" /> " +
        "<input type=\"button\" value=\"Save #" + (3 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + "\" onclick=\"javascript:PETQS_SaveSet(" + (3 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ");\" style=\"display: inline-block; width: 64px; font-size: 12px;\" /> " +
        "<input type=\"button\" value=\"Save #" + (4 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + "\" onclick=\"javascript:PETQS_SaveSet(" + (4 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ");\" style=\"display: inline-block; width: 64px; font-size: 12px;\" /><br />" +
        "<input type=\"button\" value=\"Save #" + (5 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + "\" onclick=\"javascript:PETQS_SaveSet(" + (5 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ");\" style=\"display: inline-block; width: 64px; font-size: 12px;\" /> " +
        "<input type=\"button\" value=\"Save #" + (6 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + "\" onclick=\"javascript:PETQS_SaveSet(" + (6 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ");\" style=\"display: inline-block; width: 64px; font-size: 12px;\" /> " +
        "<input type=\"button\" value=\"Save #" + (7 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + "\" onclick=\"javascript:PETQS_SaveSet(" + (7 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ");\" style=\"display: inline-block; width: 64px; font-size: 12px;\" /> " +
        "<input type=\"button\" value=\"Save #" + (8 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + "\" onclick=\"javascript:PETQS_SaveSet(" + (8 + ((PETQS_PageOn - 1) * PETQS_SetsPerPage)).toFixed(0) + ");\" style=\"display: inline-block; width: 64px; font-size: 12px;\" /><br />" +
        "<input type=\"button\" value=\"&lt;  Prev Page\" onclick=\"javascript:PETQS_PageChange(-1);\" style=\"display: inline-block; width: 132px; font-size: 12px;\" /> " +
        "<input type=\"button\" value=\"Next Page  &gt;\" onclick=\"javascript:PETQS_PageChange(1);\" style=\"display: inline-block; width: 132px; font-size: 12px;\" /><br />" +
        "</div>" +
        "</div>"
    );

    for (iSlot = 1; iSlot <= PETQS_SetsPerPage; iSlot++)
        PETQS_LoadSet(iSlot + ((PETQS_PageOn - 1) * PETQS_SetsPerPage));
};

PETQS_PageChange = function(iAmt)
{
	PETQS_PageOn += iAmt;
	if (PETQS_PageOn <= 0)
		PETQS_PageOn = PETQS_PageMax;
	if (PETQS_PageOn > PETQS_PageMax)
		PETQS_PageOn = 1;
    GM_setValue("PETQS_Page", PETQS_PageOn.toString());
	PETQS_CreateUI();
};

PETQS_UpdateSetTooltip = function(iSlot, bEmpty)
{
    oEl = jQ("#PETQS_Slotbar" + pad(iSlot, 2)).get(0);
    if (!oEl)
        return;

    if (oEl._tippy)
        oEl._tippy.destroy();

    jQ("#tooltip-PETQS_Slotbar" + pad(iSlot, 2)).remove();
    jQ("body").append("<div class=\"item-tooltip-content my-tooltip-inner\" id=\"tooltip-PETQS_Slotbar" + pad(iSlot, 2) + "\"></div>");

    if (bEmpty)
    {
        jQ("#tooltip-PETQS_Slotbar" + pad(iSlot, 2)).html
        (
            "    <h3 class=\"popover-title\">" +
            "        " + (GM_getValue("PETQS_Name" + pad(iSlot, 2)) || "Quick Set #" + iSlot.toFixed(0)) +
            "    </h3>" +
            "    <div class=\"popover-content\">" +
            "        set #" + iSlot.toFixed(0) + "<br />" +
            "        this set is empty" +
            "    </div>"
        );
    }
    else
    {
        jQ("#tooltip-PETQS_Slotbar" + pad(iSlot, 2)).html
        (
            "    <h3 class=\"popover-title\">" +
            "        " + (GM_getValue("PETQS_Name" + pad(iSlot, 2)) || "Quick Set #" + iSlot.toFixed(0)) +
            "    </h3>" +
            "    <div class=\"popover-content\">" +
            "        set #" + iSlot.toFixed(0) + "<br />" +
            "        <b>Left Click</b> to equip this set<br />" +
            "        <b>Shift Click</b> to rename this set<br />" +
            "        <b>Control Click</b> to delete this set" +
            "    </div>"
        );
    }

    tippy("#PETQS_Slotbar" + pad(iSlot, 2),
    {
        html: jQ("#tooltip-PETQS_Slotbar" + pad(iSlot, 2))[0],
        performance: !0,
        animateFill: !1,
        distance: 5
    });
};

PETQS_ClickedSet = function(iSlot, e)
{
    var bShiftPressed = false;
    var bCtrlPressed = false;

    try
	{
		if (e !== null)
        {
			if (e.shiftKey) bShiftPressed = true;
			if (e.ctrlKey)  bCtrlPressed = true;
        }
	}
	catch (err) { }

    if (bShiftPressed)
    {
        var sSetName = prompt("Enter a new name for this set:", GM_getValue("PETQS_Name" + pad(iSlot, 2)) || "Quick Set #" + iSlot.toFixed(0));
        if (sSetName !== null)
        {
            GM_setValue("PETQS_Name" + pad(iSlot, 2), sSetName.trim());
            PETQS_LoadSet(iSlot);
        }
    }
    else if (bCtrlPressed)
    {
        if (confirm("Really delete set #" + iSlot.toFixed(0) + " (\"" + (GM_getValue("PETQS_Name" + pad(iSlot, 2)) || "Quick Set #" + iSlot.toFixed(0)) + "\")?"))
        {
            GM_deleteValue("PETQS_Name" + pad(iSlot, 2));
            GM_deleteValue("PETQS_QS" + pad(iSlot, 2));
            jQ("div#PETQS_Slotbar" + pad(iSlot, 2)).html("[empty set]");
            PETQS_UpdateSetTooltip(iSlot, true);
        }
    }
    else
        PETQS_LoadSet(iSlot, true);
};

PETQS_SkinEquipped = function()
{
    return Package.meteor.global.Accounts.connection._stores.combat._getCollection()._collection._docs._map[ET.MCMF.CombatID].characterIcon;
};

PETQS_SaveSet = function(iSlot)
{
    var sSetting = "";

    sSetting += "skin&&" + PETQS_SkinEquipped() + "||";

    try
    {
        jQ.makeArray(PETQS_EquippedItems).forEach(function(oEquippedItem, index, array)
        {
            //console.log(oEquippedItem);

            try
            {
                var oEquippedItemToUse = oEquippedItem;

                if (!oEquippedItem.fields.category)
                {
                    jQ.makeArray(PETQS_AllItems).forEach(function(oThisItem, index2, array2)
                    {
                        if ((oThisItem.id === oEquippedItem.id) && (oThisItem.fields.category))
                        {
                            oEquippedItemToUse = oThisItem;
                            //console.log("--> ", oEquippedItemToUse);
                        }
                    });
                }

                sSetting +=     "item&&"
                              + oEquippedItemToUse.id + "&&"
                              + oEquippedItemToUse.fields.itemId + "&&"
                              + oEquippedItemToUse.fields.name + "&&"
                              + (oEquippedItem.fields.slot ? oEquippedItem.fields.slot : oEquippedItemToUse.fields.slot) + "&&"
                              + oEquippedItemToUse.fields.icon + "&&"
                              + (oEquippedItemToUse.fields.quality ? oEquippedItemToUse.fields.quality.toFixed(0) : "-1") + "&&"
                              + (oEquippedItemToUse.fields.enhanced ? "E" : "X") + "||";
            }
            catch (err) { console.log("Error with PETQS/saveItem: " + err); }
        });
    }
    catch (err) { console.log("Error with PETQS/saveItems: " + err); }

    try
    {
        jQ.makeArray(PETQS_EquippedAbilities).forEach(function(oEquippedAbility, index, array)
        {
            //console.log(oEquippedAbility);

            try
            {
                sSetting +=     "ability&&"
                              + oEquippedAbility.abilityId + "&&"
                              + oEquippedAbility.name + "&&"
                              + oEquippedAbility.slot + "&&"
                              + oEquippedAbility.icon + "||";
            }
            catch (err) { console.log("Error with PETQS/saveAbility: " + err); }
        });
    }
    catch (err) { console.log("Error with PETQS/saveAbilities: " + err); }

    //console.log("Save: PETQS_QS" + pad(iSlot, 2) + " = " + sSetting);

    GM_setValue("PETQS_QS" + pad(iSlot, 2), sSetting);

    PETQS_LoadSet(iSlot);
};

PETQS_LoadSet = function(iSlot, bEquip = false)
{
    var sRawSetting = GM_getValue("PETQS_QS" + pad(iSlot, 2)) || "";
    //console.log("Load: " + sRawSetting);

    if (sRawSetting === "")
    {
        PETQS_UpdateSetTooltip(iSlot, true);
        return;
    }

    var sSettingLines = jQ.makeArray(sRawSetting.split("||"));
    var sHotbarHTML = "";

    const sImageSize = "22px";

    if (bEquip)
    {
        Package.meteor.Meteor.connection._send({"msg":"method","method":"abilities.unequip","params":["head"],"id":"-1"});
        Package.meteor.Meteor.connection._send({"msg":"method","method":"abilities.unequip","params":["chest"],"id":"-1"});
        Package.meteor.Meteor.connection._send({"msg":"method","method":"abilities.unequip","params":["offHand"],"id":"-1"});
        Package.meteor.Meteor.connection._send({"msg":"method","method":"abilities.unequip","params":["mainHand"],"id":"-1"});
        Package.meteor.Meteor.connection._send({"msg":"method","method":"abilities.unequip","params":["legs"],"id":"-1"});

        var equipmentCopy = PETQS_EquippedItems.slice();

        if (equipmentCopy.length > 0)
            for (i = 0; i < equipmentCopy.length; i++)
                if (equipmentCopy[i].fields.category != "mining")
                    Package.meteor.Meteor.connection._send({"msg":"method","method":"items.unequip","params":[equipmentCopy[i].id,equipmentCopy[i].fields.itemId],"id":"-1"});
    }

    // look for skins first
    sSettingLines.forEach(function(sSettingLine, index, array)
    {
        try
        {
            var sSettingVals = jQ.makeArray(sSettingLine.split("&&"));

            if (sSettingVals[0] == "skin")
            {
                //console.log("skin: " + sSettingVals[1]);

                sHotbarHTML += "<img src=\"/icons/" + sSettingVals[1] + "\" class=\"extra-small-icon\" style=\"width: " + sImageSize + "; height: " + sImageSize + "; padding: 0px; margin: 0px; border: none;\" />";

                if (bEquip)
                {
                    //todo: use Package.meteor.global.Accounts.connection._stores.skins._getCollection()._collection
                    if (sSettingVals[1] == "mageT1HD.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["mage_t1"],"id":"-1"});
                    if (sSettingVals[1] == "mageT2HD.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["mage_t2"],"id":"-1"});
                    if (sSettingVals[1] == "damageT1HD.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["damage_t1"],"id":"-1"});
                    if (sSettingVals[1] == "damageT2HD.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["damage_t2"],"id":"-1"});
                    if (sSettingVals[1] == "tankT1HD.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["tank_t1"],"id":"-1"});
                    if (sSettingVals[1] == "tankT2HD.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["tank_t2"],"id":"-1"});
                    if (sSettingVals[1] == "phoenixT1.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["phoenix_t1"],"id":"-1"});
                    if (sSettingVals[1] == "phoenixT2.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["phoenix_t2"],"id":"-1"});
                    if (sSettingVals[1] == "crowT1.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["crow_t1"],"id":"-1"});
                    if (sSettingVals[1] == "crowT2.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["crow_t2"],"id":"-1"});
                    if (sSettingVals[1] == "vallaT1.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["valla_t1"],"id":"-1"});
                    if (sSettingVals[1] == "adalgarT1.png") Package.meteor.Meteor.connection._send({"msg":"method","method":"combat.updateCharacterIcon","params":["adalgar_t1"],"id":"-1"});
                }
            }
        }
        catch (err) { }
    });

    // look for gear
    for (i = 1; i <= 6; i++)
    {
        sSettingLines.forEach(function(sSettingLine, index, array)
        {
            try
            {
                var sSettingVals = jQ.makeArray(sSettingLine.split("&&"));

                if (sSettingVals[0] == "item")
                {
                    if ((i == 1) && (sSettingVals[4] != "mainHand")) return;
                    if ((i == 2) && (sSettingVals[4] != "offHand")) return;
                    if ((i == 3) && (sSettingVals[4] != "head")) return;
                    if ((i == 4) && (sSettingVals[4] != "neck")) return;
                    if ((i == 5) && (sSettingVals[4] != "chest")) return;
                    if ((i == 6) && (sSettingVals[4] != "legs")) return;

                    //console.log("item: " + sSettingVals[3]);

                    sHotbarHTML += "<img src=\"/icons/" + sSettingVals[5] + "\" class=\"extra-small-icon\" style=\"width: " + sImageSize + "; height: " + sImageSize + "; padding: 0px; margin: 0px; border: none;\" />";

                    if (bEquip)
                        Package.meteor.Meteor.connection._send({"msg":"method","method":"items.equip","params":[sSettingVals[1],sSettingVals[2]],"id":"-1"});
                }
            }
            catch (err) { }
        });
    }

    // look for abilities
    for (i = 1; i <= 5; i++)
    {
        sSettingLines.forEach(function(sSettingLine, index, array)
        {
            try
            {
                var sSettingVals = jQ.makeArray(sSettingLine.split("&&"));

                if (sSettingVals[0] == "ability")
                {
                    if ((i == 1) && (sSettingVals[3] != "mainHand")) return;
                    if ((i == 2) && (sSettingVals[3] != "offHand")) return;
                    if ((i == 3) && (sSettingVals[3] != "head")) return;
                    if ((i == 4) && (sSettingVals[3] != "chest")) return;
                    if ((i == 5) && (sSettingVals[3] != "legs")) return;

                    //console.log("ability: " + sSettingVals[2]);

                    sHotbarHTML += "<img src=\"/icons/" + sSettingVals[4] + "\" class=\"extra-small-icon\" style=\"width: " + sImageSize + "; height: " + sImageSize + "; padding: 0px; margin: 0px; border: none;\" />";

                    if (bEquip)
                        Package.meteor.Meteor.connection._send({"msg":"method","method":"abilities.equip","params":[sSettingVals[1]],"id":"-1"});
                }
            }
            catch (err) { }
        });
    }

    jQ("div#PETQS_Slotbar" + pad(iSlot, 2)).html(sHotbarHTML);
    PETQS_UpdateSetTooltip(iSlot, false);
};


////////////////////////////////////////////////////////////////
/////////////// ** common.js -- DO NOT MODIFY ** ///////////////
time_val = function()
{
    return CDbl(Math.floor(Date.now() / 1000));
};

IsValid = function(oObject)
{
    if (oObject === undefined) return false;
    if (oObject === null) return false;
    return true;
};

Random = function(iMin, iMax)
{
    return parseInt(iMin + Math.floor(Math.random() * iMax));
};

ShiftClick = function(oEl)
{
    if (oEl === undefined)
    {
        var shiftclick = jQ.Event("click");
        shiftclick.shiftKey = true;

        var shiftclickOrig = jQ.Event("click");
        shiftclickOrig.shiftKey = true;

        shiftclick.originalEvent = shiftclick;
        return shiftclick;
    }

    jQ(oEl).trigger(ShiftClick());
};

if (!String.prototype.replaceAll)
    String.prototype.replaceAll = function(search, replace) { return ((replace === undefined) ? this.toString() : this.replace(new RegExp('[' + search + ']', 'g'), replace)); };

if (!String.prototype.startsWith)
    String.prototype.startsWith = function(search, pos) { return this.substr(((!pos) || (pos < 0)) ? 0 : +pos, search.length) === search; };

CInt = function(v)
{
	try
	{
		if (!isNaN(v)) return Math.floor(v);
		if (typeof v === 'undefined') return parseInt(0);
		if (v === null) return parseInt(0);
		var t = parseInt(v);
		if (isNaN(t)) return parseInt(0);
		return Math.floor(t);
	}
	catch (err) { }

	return parseInt(0);
};

CDbl = function(v)
{
	try
	{
		if (!isNaN(v)) return parseFloat(v);
		if (typeof v === 'undefined') return parseFloat(0.0);
		if (v === null) return parseFloat(0.0);
		var t = parseFloat(v);
		if (isNaN(t)) return parseFloat(0.0);
		return t;
	}
	catch (err) { }

	return parseFloat(0.0);
};

// dup of String.prototype.startsWith, but uses indexOf() instead of substr()
startsWith = function (haystack, needle) { return (needle === "") || (haystack.indexOf(needle) === 0); };
endsWith   = function (haystack, needle) { return (needle === "") || (haystack.substring(haystack.length - needle.length) === needle); };

ChopperBlank = function (sText, sSearch, sEnd)
{
	var sIntermediate = "";

	if (sSearch === "")
		sIntermediate = sText.substring(0, sText.length);
	else
	{
		var iIndexStart = sText.indexOf(sSearch);
		if (iIndexStart === -1)
			return "";

		sIntermediate = sText.substring(iIndexStart + sSearch.length);
	}

	if (sEnd === "")
		return sIntermediate;

	var iIndexEnd = sIntermediate.indexOf(sEnd);

	return (iIndexEnd === -1) ? sIntermediate : sIntermediate.substring(0, iIndexEnd);
};

CondenseSpacing = function(text)
{
	while (text.indexOf("  ") !== -1)
		text = text.replace("  ", " ");
	return text;
};

pad = function(sText, iWidth, sChar)
{
    sChar = ((sChar !== undefined) ? sChar : ('0'));
    sText = sText.toString();
    return ((sText.length >= iWidth) ? (sText) : (new Array(iWidth - sText.length + 1).join(sChar) + sText));
};

is_visible = (function () {
    var x = window.pageXOffset ? window.pageXOffset + window.innerWidth - 1 : 0,
        y = window.pageYOffset ? window.pageYOffset + window.innerHeight - 1 : 0,
        relative = !!((!x && !y) || !elementFromPoint(x, y));
        function inside(child, parent) {
            while(child){
                if (child === parent) return true;
                child = child.parentNode;
            }
        return false;
    };
    return function (elem) {
        if (
            hidden ||
            elem.offsetWidth==0 ||
            elem.offsetHeight==0 ||
            elem.style.visibility=='hidden' ||
            elem.style.display=='none' ||
            elem.style.opacity===0
        ) return false;
        var rect = elem.getBoundingClientRect();
        if (relative) {
            if (!inside(elementFromPoint(rect.left + elem.offsetWidth/2, rect.top + elem.offsetHeight/2),elem)) return false;
        } else if (
            !inside(elementFromPoint(rect.left + elem.offsetWidth/2 + window.pageXOffset, rect.top + elem.offsetHeight/2 + window.pageYOffset), elem) ||
            (
                rect.top + elem.offsetHeight/2 < 0 ||
                rect.left + elem.offsetWidth/2 < 0 ||
                rect.bottom - elem.offsetHeight/2 > (window.innerHeight || documentElement.clientHeight) ||
                rect.right - elem.offsetWidth/2 > (window.innerWidth || documentElement.clientWidth)
            )
        ) return false;
        if (window.getComputedStyle || elem.currentStyle) {
            var el = elem,
                comp = null;
            while (el) {
                if (el === document) {break;} else if(!el.parentNode) return false;
                comp = window.getComputedStyle ? window.getComputedStyle(el, null) : el.currentStyle;
                if (comp && (comp.visibility=='hidden' || comp.display == 'none' || (typeof comp.opacity !=='undefined' && comp.opacity != 1))) return false;
                el = el.parentNode;
            }
        }
        return true;
    };
})();
////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////
////////////// ** common_ET.js -- DO NOT MODIFY ** /////////////

if (window.ET === undefined) window.ET = { };
if (window.ET.MCMF === undefined) // MeanCloud mod framework
{
    window.ET.MCMF =
    {
        TryingToLoad: false,
        WantDebug: false,
        WantFasterAbilityCDs: false,

        InBattle: false,
        FinishedLoading: false,
        Initialized: false,
        AbilitiesReady: false,
        InitialAbilityCheck: true,
        TimeLeftOnCD: 9999,
        TimeLastFight: 0,

        CombatID: undefined, // technically not required

        ToastMessageSuccess: function(msg)
        {
            toastr.success(msg);
        },

        ToastMessageWarning: function(msg)
        {
            toastr.warning(msg);
        },

        EventSubscribe: function(sEventName, fnCallback, sNote)
        {
            if (window.ET.MCMF.EventSubscribe_events === undefined)
                window.ET.MCMF.EventSubscribe_events = [];

            var newEvtData = {};
                newEvtData.name = ((!sEventName.startsWith("ET:")) ? ("ET:" + sEventName) : (sEventName));
                newEvtData.callback = fnCallback;
                newEvtData.note = sNote;

            window.ET.MCMF.EventSubscribe_events.push(newEvtData);

            /*
            jQ("div#ET_meancloud_bootstrap").off("ET:" + sEventName.trim()).on("ET:" + sEventName.trim(), function()
            {
                window.ET.MCMF.EventSubscribe_events.forEach(function(oThisEvent, index, array)
                {
                    if (sEventName === oThisEvent.name)
                    {
                        if (window.ET.MCMF.WantDebug) console.log("FIRING '" + oThisEvent.name + "'!" + ((oThisEvent.note === undefined) ? "" : " (" + oThisEvent.note + ")"));
                        oThisEvent.callback();
                    }
                });
            });
            */

            if (window.ET.MCMF.WantDebug) console.log("Added event subscription '" + sEventName + "'!" + ((sNote === undefined) ? "" : " (" + sNote + ")"));
        },

        EventTrigger: function(sEventName)
        {
            //jQ("div#ET_meancloud_bootstrap").trigger(sEventName);

            if (window.ET.MCMF.EventSubscribe_events === undefined) return;

            window.ET.MCMF.EventSubscribe_events.forEach(function(oThisEvent, index, array)
            {
                if (sEventName === oThisEvent.name)
                {
                    if (window.ET.MCMF.WantDebug) console.log("FIRING '" + oThisEvent.name + "'!" + ((oThisEvent.note === undefined) ? "" : " (" + oThisEvent.note + ")"));
                    try { oThisEvent.callback(); } catch (err) { if (window.ET.MCMF.WantDebug) console.log("Exception: " + err); }
                }
            });
        },

        MeteorCall: function(sMethod, oParam1, oParam2, sMsgSuccess, sMsgFailure)
        {
            Package.meteor.Meteor.call("crafting.craftItem", sRecipeID, iBatchAmt, function(errResp)
            {
                if (errResp)
                    window.ET.MCMF.ToastMessageWarning(sMsgFailure);
                else
                    window.ET.MCMF.ToastMessageSuccess(sMsgSuccess);
            });
        },

        FasterAbilityUpdates: function()
        {
            try
            {
                if ((window.ET.MCMF.WantFasterAbilityCDs) && (window.ET.MCMF.FinishedLoading) && (!window.ET.MCMF.InBattle) && (!window.ET.MCMF.AbilitiesReady))
                    Meteor.call("abilities.gameUpdate", function(e, t) { });
            }
            catch (err) { }

            setTimeout(window.ET.MCMF.FasterAbilityUpdates, 2000);
        },

        AbilityCDTrigger: function()
        {
            try
            {
                bStillInCombat = window.ET.MCMF.InBattle || ((time_val() - window.ET.MCMF.TimeLastFight) < 3);

                if ((window.ET.MCMF.FinishedLoading) && (!bStillInCombat))
                {
                    iTotalCD = 0;
                    iTotalCDTest = 0;
                    iHighestCD = 0;

                    window.ET.MCMF.GetAbilities().forEach(function(oThisAbility, index, array)
                    {
                        if (oThisAbility.equipped)
                        {
                            if (parseInt(oThisAbility.currentCooldown) > 0)
                            {
                                iTotalCD += parseInt(oThisAbility.currentCooldown);
                                if (iHighestCD < parseInt(oThisAbility.currentCooldown))
                                    iHighestCD = parseInt(oThisAbility.currentCooldown);
                            }
                        }

                        iTotalCDTest += parseInt(oThisAbility.cooldown);
                    });

                    if ((iTotalCDTest > 0) && (iTotalCD === 0))
                    {
                        if (!window.ET.MCMF.AbilitiesReady)
                        {
                            if (!window.ET.MCMF.InitialAbilityCheck)
                            {
                                if (window.ET.MCMF.WantDebug) console.log("<-- triggering ET:abilitiesReady -->");
                                window.ET.MCMF.EventTrigger("ET:abilitiesReady");
                                //jQ("div#ET_meancloud_bootstrap").trigger("ET:abilitiesReady");
                            }
                        }

                        window.ET.MCMF.AbilitiesReady = true;
                        window.ET.MCMF.TimeLeftOnCD = 0;
                    }
                    else
                    {
                        window.ET.MCMF.AbilitiesReady = false;
                        window.ET.MCMF.TimeLeftOnCD = iHighestCD;
                    }

                    window.ET.MCMF.InitialAbilityCheck = false;
                }
                else
                {
                    window.ET.MCMF.AbilitiesReady = false;
                    window.ET.MCMF.TimeLeftOnCD = 9999;
                }
            }
            catch (err) { }

            setTimeout(window.ET.MCMF.AbilityCDTrigger, 500);
        },

        InitMeteorTriggers: function()
        {
            if ((Package.meteor.Meteor === undefined) || (Package.meteor.Meteor.connection === undefined) || (Package.meteor.Meteor.connection._stream === undefined))
            {
                setTimeout(window.ET.MCMF.InitMeteorTriggers, 100);
                return;
            }

            Package.meteor.Meteor.connection._stream.on('message', function(sMeteorRawData)
            {
                if (window.ET.MCMF.CombatID === undefined)
                {
                    try
                    {
                        oDataTemp = Package.meteor.global.Accounts.connection._stores.combat._getCollection()._collection._docs._map;
                        window.ET.MCMF.CombatID = oDataTemp[Object.keys(oDataTemp)[0]]._id;
                    }
                    catch (err) { }
                }

                try
                {
                    oMeteorData = JSON.parse(sMeteorRawData);

                    /////////////////////////////////////////////////////////////////////////////////////////////////////////
                    //
                    //  BACKUP TO RETRIEVE USER AND COMBAT IDS
                    //
                    if (oMeteorData.collection === "users")
                        if ((window.ET.MCMF.UserID === undefined) || (window.ET.MCMF.UserID.length !== 17))
                            window.ET.MCMF.UserID = oMeteorData.id;

                    if (oMeteorData.collection === "combat")
                        if ((window.ET.MCMF.T_CombatID === undefined) || (window.ET.MCMF.CombatID.length !== 17))
                            if (oMeteorData.fields.owner === window.ET.MCMF.UserID)
                                window.ET.MCMF.CombatID = oMeteorData.id;
                    //
                    /////////////////////////////////////////////////////////////////////////////////////////////////////////

                    if (window.ET.MCMF.FinishedLoading)
                    {
                        if (oMeteorData.collection === "battlesList")
                        {
                            window.ET.MCMF.IsDemon = false;
                            window.ET.MCMF.AbilitiesReady = false;

                            if ((oMeteorData.msg === "added") || (oMeteorData.msg === "removed"))
                            {
                                window.ET.MCMF.InBattle = (oMeteorData.msg === "added");
                                if (window.ET.MCMF.WantDebug) console.log("<-- triggering ET:combat" + (((oMeteorData.msg === "added")) ? ("Start") : ("End")) + " -->");
                                window.ET.MCMF.EventTrigger("ET:combat" + (((oMeteorData.msg === "added")) ? ("Start") : ("End")));
                                //jQ("div#ET_meancloud_bootstrap").trigger("ET:combat" + (((oMeteorData.msg === "added")) ? ("Start") : ("End")));
                            }
                        }

                        if ((oMeteorData.collection === "battles") && (oMeteorData.msg === "added"))
                        {
                            if (oMeteorData.fields.finished)
                            {
                                window.ET.MCMF.WonLast = oMeteorData.fields.win;
                                window.ET.MCMF.TimeLastFight = time_val();

                                if (!oMeteorData.fields.win)
                                    window.ET.MCMF.HP = 0;

                                if (window.ET.MCMF.WantDebug) console.log("<-- triggering ET:combat" + ((oMeteorData.fields.win) ? ("Won") : ("Lost")) + " -->");
                                window.ET.MCMF.EventTrigger("ET:combat" + ((oMeteorData.fields.win) ? ("Won") : ("Lost")));
                                //jQ("div#ET_meancloud_bootstrap").trigger("ET:combat" + ((oMeteorData.fields.win) ? ("Won") : ("Lost")));
                            }
                        }
                    }

                    try
                    {
                        if (window.ET.MCMF.FinishedLoading)
                        {
                            if (oMeteorData.id)
                            {
                                if (oMeteorData.id.startsWith("battles-"))
                                {
                                    if (oMeteorData.msg !== "removed")
                                    {
                                        battleID = oMeteorData.id;
                                        battleData = JSON.parse(oMeteorData.fields.value);

                                        jQ.makeArray(battleData.units).forEach(function(currentPlayer, index, array)
                                        {
                                            try
                                            {
                                                if (currentPlayer.name === window.ET.MCMF.UserName)
                                                {
                                                    jQ.makeArray(currentPlayer.buffs).forEach(function(currentBuff, index2, array2)
                                                     {
                                                        try
                                                        {
                                                            if (currentBuff.id === "demons_heart")
                                                            {
                                                                if (currentBuff.data.active)
                                                                {
                                                                    if (!window.ET.MCMF.IsDemon)
                                                                    {
                                                                        window.ET.MCMF.IsDemon = true;

                                                                        if (window.ET.MCMF.WantDebug) console.log("<-- triggering ET:combat:buffDemon -->");
                                                                        window.ET.MCMF.EventTrigger("ET:combat:buffDemon");
                                                                        //jQ("div#ET_meancloud_bootstrap").trigger("ET:combat:buffDemon");
                                                                    }
                                                                }
                                                            }
                                                        }
                                                        catch (err) { }
                                                    });

                                                    return true; // break out of forEach()
                                                }
                                            }
                                            catch (err) { }
                                        });
                                    }
                                }
                            }
                        }
                    }
                    catch (err) { }
                }
                catch (err) { }

                try
                {
                    //todo: use life data from Meteor vs captured meteor response data
                    oMeteorData = JSON.parse(sMeteorRawData);

                    if (oMeteorData.collection === "combat")
                    {
                        if ((oMeteorData.fields.owner === window.ET.MCMF.UserID) || (oMeteorData.id === window.ET.MCMF.CombatID))
                        {
                            window.ET.MCMF.HP  = oMeteorData.fields.stats.health;
                            window.ET.MCMF.NRG = oMeteorData.fields.stats.energy;
                        }
                    }
                }
                catch (err) { }
            });
        },

        AbilityCDCalc: function()
        {
            iTotalCD = 0;
            iTotalCDTest = 0;
            iHighestCD = 0;

            window.ET.MCMF.GetAbilities().forEach(function(oThisAbility, index, array)
            {
                if (oThisAbility.equipped)
                {
                    if (parseInt(oThisAbility.currentCooldown) > 0)
                    {
                        iTotalCD += parseInt(oThisAbility.currentCooldown);
                        if (iHighestCD < parseInt(oThisAbility.currentCooldown))
                            iHighestCD = parseInt(oThisAbility.currentCooldown);
                    }
                }

                iTotalCDTest += parseInt(oThisAbility.cooldown);
            });

            if ((iTotalCDTest > 0) && (iTotalCD === 0))
            {
                if (!window.ET.MCMF.AbilitiesReady)
                {
                    if (!window.ET.MCMF.InitialAbilityCheck)
                    {
                        if (window.ET.MCMF.WantDebug) console.log("<-- triggering ET:abilitiesReady -->");
                        window.ET.MCMF.EventTrigger("ET:abilitiesReady");
                        //jQ("div#ET_meancloud_bootstrap").trigger("ET:abilitiesReady");
                    }
                }

                window.ET.MCMF.AbilitiesReady = true;
                window.ET.MCMF.TimeLeftOnCD = 0;
            }
            else
            {
                window.ET.MCMF.AbilitiesReady = false;
                window.ET.MCMF.TimeLeftOnCD = iHighestCD;
            }

            window.ET.MCMF.InitialAbilityCheck = false;
        },

        GetAbilities: function()
        {
            return Object.keys(window.ET.MCMF.AbilityManager._collection._docs._map).map(key => window.ET.MCMF.AbilityManager._collection._docs._map[key])[0].learntAbilities;
        },

        GetAdventures: function()
        {
            return Object.keys(window.ET.MCMF.AdventureManager._collection._docs._map).map(key => window.ET.MCMF.AdventureManager._collection._docs._map[key])[0].adventures;
        },

        GetChats: function()
        {
            return Object.keys(window.ET.MCMF.ChatManager._collection._docs._map).map(key => window.ET.MCMF.ChatManager._collection._docs._map[key]);
        },

        GetItems: function()
        {
            return Object.keys(window.ET.MCMF.ItemManager._collection._docs._map).map(key => window.ET.MCMF.ItemManager._collection._docs._map[key]);
        },

        // need a better way to check if the game has loaded basic data, but this is fine for now
        Setup: function()
        {
            if ((!window.ET.MCMF.TryingToLoad) && (!window.ET.MCMF.FinishedLoading))
            {
                // use whatever version of jQuery available to us
                $("body").append("<div id=\"ET_meancloud_bootstrap\" style=\"visibility: hidden; display: none;\"></div>");
                window.ET.MCMF.TryingToLoad = true;
                window.ET.MCMF.Setup_Initializer();
            }
        },

        Setup_Initializer: function()
        {
            // wait for Meteor availability
            if ((Package === undefined) || (Package.meteor === undefined) || (Package.meteor.Meteor === undefined) || (Package.meteor.Meteor.connection === undefined) || (Package.meteor.Meteor.connection._stream === undefined))
            {
                setTimeout(window.ET.MCMF.Setup_Initializer, 10);
                return;
            }

            if (!window.ET.MCMF.Initialized)
            {
                window.ET.MCMF.Initialized = true;
                window.ET.MCMF.Setup_SendDelayedInitializer();
                window.ET.MCMF.InitMeteorTriggers();
                window.ET.MCMF.Setup_remaining();
            }
        },

        Setup_SendDelayedInitializer: function()
        {
            try
            {
                jQ("div#ET_meancloud_bootstrap").trigger("ET:initialized");
                window.ET.MCMF.EventTrigger("ET:initialized");
                //if (window.ET.MCMF.WantDebug) console.log("<-- triggering ET:initialized -->");
            }
            catch (err)
            {
                setTimeout(window.ET.MCMF.Setup_SendDelayedInitializer, 100);
            }
        },

        Setup_remaining: function()
        {
            try
            {
                window.ET.MCMF.UserID = Package.meteor.global.Accounts.connection._userId;
                window.ET.MCMF.UserName = Package.meteor.global.Accounts.connection._stores.users._getCollection()._collection._docs._map[Package.meteor.global.Accounts.connection._userId].username;
                try
                {
                    oDataTemp = Package.meteor.global.Accounts.connection._stores.combat._getCollection()._collection._docs._map;
                    Object.keys(oDataTemp).forEach(function(oDataTempItem, index, array)
                    {
                        if (oDataTempItem.owner === window.ET.MCMF.UserID)
                            window.ET.MCMF.CombatID = oDataTempItem._id;
                    });
                }
                catch (err) { }

                window.ET.MCMF.AbilityManager = Package.meteor.global.Accounts.connection._stores.abilities._getCollection();
                window.ET.MCMF.AdventureManager = Package.meteor.global.Accounts.connection._stores.adventures._getCollection();
                window.ET.MCMF.ChatManager = Package.meteor.global.Accounts.connection._stores.simpleChats._getCollection();
                window.ET.MCMF.ItemManager = Package.meteor.global.Accounts.connection._stores.items._getCollection();

                if (window.ET.MCMF.GetAbilities().length < 0) throw "Not loaded yet: no abilities";
                if (window.ET.MCMF.GetItems().length < 0) throw "Not loaded yet: no items";
                if (window.ET.MCMF.GetChats().length < 0) throw "Not loaded yet: no chats";

                // if the above is all good, then this should be no problem:

                window.ET.MCMF.AbilityCDTrigger();     // set up ability CD trigger
                window.ET.MCMF.AbilityCDCalc();
                window.ET.MCMF.FasterAbilityUpdates(); // set up faster ability updates (do not disable, this is controlled via configurable setting)

                // trigger finished-loading event
                if (!window.ET.MCMF.FinishedLoading)
                {
                    if (window.ET.MCMF.WantDebug) console.log("<-- triggering ET:loaded -->");
                    window.ET.MCMF.EventTrigger("ET:loaded");
                    //jQ("div#ET_meancloud_bootstrap").trigger("ET:loaded");
                    window.ET.MCMF.FinishedLoading = true;
                }

                document.ET = window.ET;
            }
            catch (err)
            {
                // any errors and we retry setup
                setTimeout(window.ET.MCMF.Setup_remaining, 500);
            }
        },

        Loaded: function(fnCallback, sNote)
        {
            if (!window.ET.MCMF.FinishedLoading)
                window.ET.MCMF.EventSubscribe("loaded", fnCallback, sNote);
            else
                fnCallback();
        },

        Ready: function(fnCallback, sNote)
        {
            if (!window.ET.MCMF.Initialized)
                window.ET.MCMF.EventSubscribe("initialized", fnCallback, sNote);
            else
                fnCallback();
        }
    };

    window.ET.MCMF.Setup();
}
////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////
////////// ** CORE SCRIPT STARTUP -- DO NOT MODIFY ** //////////
function LoadJQ(callback) {
    if (window.jQ === undefined) { var script=document.createElement("script");script.setAttribute("src","//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js");script.addEventListener('load',function() {
        var subscript=document.createElement("script");subscript.textContent="window.jQ=jQuery.noConflict(true);("+callback.toString()+")();";document.body.appendChild(subscript); },
    !1);document.body.appendChild(script); } else callback(); } LoadJQ(startup);
////////////////////////////////////////////////////////////////