runnan

SBC Autofill with player swapping

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         runnan
// @namespace    http://tampermonkey.net/
// @version      2.0.1
// @description  SBC Autofill with player swapping
// @license      MIT
// @match        https://www.ea.com/ea-sports-fc/ultimate-team/web-app/*
// @match        https://www.easports.com/*/ea-sports-fc/ultimate-team/web-app/*
// @match        https://www.ea.com/*/ea-sports-fc/ultimate-team/web-app/*
// @run-at       document-end
// ==/UserScript==

/*
 * Script Usage Disclaimer
 *
 * This script is provided "as is," without warranty of any kind, express or implied.
 * The author shall not be liable for any damages arising out of the use of this script.
 * Use at your own risk and in compliance with the target site's terms of service and applicable laws.
 */
(function () {
    'use strict';
    let page = unsafeWindow;

    // Utility: sleep function
    const sleep = ms => new Promise(res => setTimeout(res, ms));

    // Utility: simulate click on element
    function simulateClick(el) {
        if (!el) {
            console.log('[SBC Autofill] Element not found for click');
            return false;
        }
        const r = el.getBoundingClientRect();
        ['mousedown', 'mouseup', 'click'].forEach(t =>
            el.dispatchEvent(new MouseEvent(t, {
                bubbles: true, cancelable: true,
                clientX: r.left + r.width / 2,
                clientY: r.top + r.height / 2,
                button: 0
            }))
        );
        return true;
    }

    // Utility: wait for element to appear
    function waitForElement(selector, timeout = 5000) {
        return new Promise(resolve => {
            const start = Date.now();
            (function poll() {
                const el = document.querySelector(selector);
                if (el) return resolve(el);
                if (Date.now() - start > timeout) return resolve(null);
                setTimeout(poll, 200);
            })();
        });
    }

    // Main SBC autofill function
    async function sbcAutofill() {
        console.log('[SBC Autofill] Starting...');

        // Step 1: Click SBC squad autofill button
        const autofillBtn = Array.from(document.querySelectorAll('button.btn-standard.call-to-action')).find(btn => btn.textContent === 'SBC squad autofill');
        if (!autofillBtn) {
            console.log('[SBC Autofill] Autofill button not found');
            return;
        }
        console.log('[SBC Autofill] Clicking autofill button');
        simulateClick(autofillBtn);
        await sleep(1000);

        // Step 2: Click modal confirmation button (OK button)
        const confirmBtn = await waitForElement('body > div.view-modal-container.form-modal > section > div > div > button:nth-child(1)', 3000);
        if (confirmBtn) {
            console.log('[SBC Autofill] Clicking OK button');
            simulateClick(confirmBtn);
            await sleep(5000); // Wait 5 seconds for squad to load
        }

        // Step 3: Loop through 11 players (div:nth-child(2) through div:nth-child(12))
        for (let i = 2; i <= 12; i++) {
            console.log(`[SBC Autofill] Processing player slot ${i - 1}/11`);

            // Click player slot (use partial class match to handle different formations)
            const playerSelector = `body > main > section > section > div.ut-navigation-container-view--content > div > div > div > div.ut-draggable > div.ut-squad-pitch-view.concept.sbc > div:nth-child(${i})`;
            const playerSlot = document.querySelector(playerSelector);
            if (!playerSlot) {
                console.log(`[SBC Autofill] Player slot ${i} not found, skipping`);
                continue;
            }
            simulateClick(playerSlot);
            await sleep(1000);

            // Step 4.1: Check for "Swap Meets Requirements Players" button
            const swapBtnSpan = Array.from(document.querySelectorAll('span.btn-text')).find(span => span.textContent === 'Swap Meets Requirements Players');

            if (swapBtnSpan) {
                console.log('[SBC Autofill] Found Swap button, clicking');
                const swapBtn = swapBtnSpan.closest('button');
                if (swapBtn) {
                    simulateClick(swapBtn);
                    await sleep(1000);

                    // Step 4.2: Try up to 5 items in list, skip FSU locked, academy graduate, or rating >= 84
                    const listBase = 'body > main > section > section > div.ut-navigation-container-view--content > div > div > section > div.ut-navigation-container-view--content > div > div.paginated-item-list.ut-pinned-list > ul > li';

                    for (let j = 1; j <= 5; j++) {
                        const itemBtn = document.querySelector(`${listBase}:nth-child(${j}) > button`);
                        const ratingEl = document.querySelector(`${listBase}:nth-child(${j}) > div > div.entityContainer > div.small.player.item > div.ut-item-view--main.ut-item-view > div > div.rating`);
                        const fsuLocked = document.querySelector(`${listBase}:nth-child(${j}) > div > div.entityContainer > div.name.fsulocked`);
                        const academyGraduate = document.querySelector(`${listBase}:nth-child(${j}) > div > div.entityContainer > div.small.player.item > div.ut-item-player-state-indicator-view.academy-graduate`);

                        if (!itemBtn) {
                            console.log(`[SBC Autofill] Item ${j} not found, stopping search`);
                            break;
                        }

                        if (fsuLocked) {
                            console.log(`[SBC Autofill] Item ${j} - FSU locked, trying next`);
                            continue;
                        }
                        if (academyGraduate) {
                            console.log(`[SBC Autofill] Item ${j} - Academy graduate, trying next`);
                            continue;
                        }
                        if (ratingEl) {
                            const rating = parseInt(ratingEl.textContent, 10);
                            if (rating >= 84) {
                                console.log(`[SBC Autofill] Item ${j} - rating ${rating} >= 84, trying next`);
                                continue;
                            }
                            console.log(`[SBC Autofill] Clicking item ${j} (rating: ${rating})`);
                            simulateClick(itemBtn);
                            await sleep(1000);
                            break; // Found valid player, exit loop
                        }
                    }
                }
            } else {
                console.log('[SBC Autofill] No Swap button found for this slot');
            }
        }

        console.log('[SBC Autofill] Complete!');
    }

    // Initialize single button
    function initButton() {
        const btn = document.createElement('button');
        btn.textContent = 'SBC Autofill';
        Object.assign(btn.style, {
            position: 'fixed',
            bottom: '40px',
            right: '40px',
            padding: '10px 20px',
            background: '#ffd700',
            border: 'none',
            borderRadius: '6px',
            fontSize: '14px',
            fontWeight: 'bold',
            cursor: 'pointer',
            zIndex: 9999
        });
        btn.addEventListener('click', sbcAutofill);
        document.body.appendChild(btn);
        console.log('[SBC Autofill] Button initialized');
    }

    page.addEventListener('load', initButton);
})();