Flight Rising Baldwin

Automatically transmutes items from your list.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Flight Rising Baldwin
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  Automatically transmutes items from your list.
// @author       Triggernometry
// @match        https://www1.flightrising.com/trading/baldwin/transmute*
// @grant        GM_setValue
// @grant        GM_getValue
// @license      GNU GPLv3
// ==/UserScript==

// wait until page load, then run main
$(document).ready(main);

// Categories are food, mats, app, fam, other

var transmuteItems = {
    "food"      : [],
    "mats"      : [],
    "app"       : [],
    "fam"       : [],
    "other"     : []
};

// set this to true to automatically melt down all food items with a point value of 2.
// the script will check the list if it doesn't find any 2-value food items, so you can still fill out the list if you use this option.
var autoMeltFood = false;

// these are used across all/most functions
var toggleState = GM_getValue('toggleState', false);
var toggleDisplay = ["OFF (click to toggle)",
                     "ON (click to toggle)"];

function buildGUI() {
    console.log("toggleDisplay:", toggleDisplay);
    // set up GUI box
    $('body').prepend("<div id=\"familiarbox\">" +
                      "    <div style=\"text-align: center; color: #e8cc9f; font: bold 7.8pt/30px tahoma; background: #731d08; margin: -10px -10px 10px;\">Auto Brewing</div>" +
                      // set toggle display to whatever it was before new page was loaded (or off, if page has never beeen loaded this session)
                      "    <button id=\"onOffDisplay\">" + toggleDisplay[toggleState ? 1 : 0] + "</button>" +
                      "</div>" +
                      "<style>" +
                      "    #familiarbox label {" +
                      "        float: inherit;" +
                      "    }" +
                      "    #familiarbox {" +
                      "        padding: 10px;" +
                      "        border: 1px solid #000;" +
                      "        position: fixed;" +
                      "        top: 0;" +
                      "        left: 0;" +
                      "        background: #fff;" +
                      "        z-index: 1002;" +
                      "    }" +
                      "    #turnOff," +
                      "    #turnOn {" +
                      "        border: 0;" +
                      "        background-color: #dcd6c8;" +
                      "        padding: 5px 10px;" +
                      "        color: #731d08;" +
                      "        margin: auto;" +
                      "        box-shadow: 0 1px 3px #999;" +
                      "        border-radius: 5px;" +
                      "        text-shadow: 0 1px 1px #FFF;" +
                      "        border-bottom: 1px solid #222;" +
                      "        cursor: pointer;" +
                      "        display: block;" +
                      "        font: bold 11px arial;" +
                      "        transition: 0.1s;" +
                      "    }" +
                      "    #onOffDisplay {" +
                      "        border: 0;" +
                      "        background-color: #dcd6c8;" +
                      "        padding: 5px 10px;" +
                      "        color: #731d08;" +
                      "        margin: auto;" +
                      "        box-shadow: 0 1px 3px #999;" +
                      "        border-radius: 5px;" +
                      "        text-shadow: 0 1px 1px #FFF;" +
                      "        border-bottom: 1px solid #222;" +
                      "        cursor: pointer;" +
                      "        display: block;" +
                      "        font: bold 11px arial;" +
                      "        transition: 0.1s;" +
                      "    }" +
                      "    #turnOff:hover," +
                      "    #turnOn:hover {" +
                      "        background-color: #bfb9ac;" +
                      "        color: #731d08;" +
                      "    }" +
                      "</style>"
                     );

    // set the toggle click behavior
    $('#onOffDisplay').click(function(){
        toggleState = !toggleState;
        GM_setValue('toggleState', toggleState);

        if(toggleState) {
            $('#onOffDisplay').html(toggleDisplay[1]);
        }
        else {
            $('#onOffDisplay').html(toggleDisplay[0]);
        }
    });
}

async function getFood(maxPoints) {
    // switch to food category tab, if not already selected
    while(document.querySelector('#swaptabs > a[data-tab-id="food"]').className != 'generic-hoard-tab generic-hoard-tab-selected') {
        console.log("Swapping to food tab");
        let chooseCategory = document.querySelector('#swaptabs > a[data-tab-id="food"]').click();
        await sleep(2000);
    }

    // get all items in category
    let itemList = document.querySelectorAll('#itempage > span > a');

    // compare to own list of allowed items
    for (const node of itemList) {
        // get tooltip name
        var tooltipID = node.getAttribute('rel');
        // get first matching tooltip. this might fail if similar tooltips exist, like #17 and #177? need to test
        var tooltip = document.querySelectorAll(`${tooltipID} .foodval > strong`)[0];
        //console.log("Tooltip", tooltipID, "Foodval", tooltip.firstChild.data);
        var foodPoints = Number(tooltip.firstChild.data);

        if(foodPoints <= maxPoints ) {
            // if allowed item found, set and break loop
            console.log("Found food:", node);
            return node;
        }
    }

    //if reached end of loop without returning, no valid food found
    return null;
}

async function getMatchingTransmutable() {
    for (const key of Object.keys(transmuteItems)) {
        let valueList = transmuteItems[key];
        console.log("key:", key);
        // switch to category tab
        let chooseCategory = document.querySelector(`#swaptabs > a[data-tab-id="${key}"]`).click();
        await sleep(2000);

        // get all items in category
        let itemList = document.querySelectorAll('#itempage > span > a');

        // compare to own list of allowed items
        for (const node of itemList) {
            if(valueList.includes(node.getAttribute('data-name'))) {
                // if allowed item found, return and break loops
                return node;
            }
        }
    }

    //if reached end of loop without returning, no item found
    return null;
}

async function collectItem(){
    await sleep(2000);
    let collectDoneItem = document.querySelector('input[value="Collect!"]').click();
    // wait for page to load after click
    // await collectDoneItem.DOMContentLoaded();
    await sleep(2000);
    location.reload();
}

async function brewingWait(){
    let brewingTime = document.querySelector('#baldwin-timer-value').getAttribute('data-seconds-left');
    brewingTime = parseInt(brewingTime) + 3;
    console.log(`Now waiting for ${brewingTime} seconds. Please Stand by.`)
    await sleep(brewingTime * 1000);
    location.reload();
}

async function transmute(){
    let clickTransmuteButton = document.querySelector('#baldwin-transmute-btn');
    console.log("Click return object:", clickTransmuteButton);

    // wait for item load
    // if Transmute button is clicked multiple times, page breaks
    while(!document.querySelector('#ui-id-1'))
    {
        await sleep(2000);
        clickTransmuteButton.click();
        await sleep(2000);
    }

    var transmuteSelection;

    if (autoMeltFood) {
        transmuteSelection = await getFood(2);
    }

    if (!transmuteSelection) {
        transmuteSelection = await getMatchingTransmutable();
    }

    // if not null, item found
    if(transmuteSelection) {
        console.log("Selected food:", transmuteSelection);

        transmuteSelection.click();
        await sleep(1000);
        let transmuteStart = document.querySelector('#attch').click();
        await sleep(2000);
        let transmuteConfirm = document.querySelector('#transmute-confirm-ok').click();
    }
    // otherwise, reached end of items without findin a match. Exit.
    else {
        console.log("Reached end without finding a match. Nothing to brew.");
        return 0;
    }
}

function sleep(ms) {
    console.log(`Sleebs ${ms} ms!`);
    return new Promise(resolve => setTimeout(resolve, ms));
}

function main(){
    buildGUI();

    // only if on
    if (toggleState == true){
        let idle = document.querySelector('#plus-button-container');
        let brewing = document.querySelector('.baldwin-cauldron-brewing');
        let done = document.querySelector('.baldwin-cauldron-done');

        if(done){
            collectItem();
        } else if (brewing){
            brewingWait();
        } else if(idle){
            transmute();
        }
    }
}