Tribal Wars Resource Buyer (Multi-language)

Automate buying resources in Tribal Wars with premium points limit - works in all languages

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Tribal Wars Resource Buyer (Multi-language)
// @namespace    http://tampermonkey.net/
// @version      1.4.0
// @description  Automate buying resources in Tribal Wars with premium points limit - works in all languages
// @author       ricardofauch (modified)
// @match        https://*.die-staemme.de/game.php?village=*&screen=market&mode=exchange
// @match        https://*.tribalwars.*/game.php?village=*&screen=market&mode=exchange
// @match        https://*.plemiona.pl/game.php?village=*&screen=market&mode=exchange
// @match        https://*.tribal-wars.*/game.php?village=*&screen=market&mode=exchange
// @grant        GM_getValue
// @grant        GM_setValue
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Default configuration
    const DEFAULT_CONFIG = {
        MAX_PREMIUM_POINTS: 300,
        PREMIUM_POINTS_TIMEOUT: 600000, // 10 minutes in ms
        PURCHASE_PERCENTAGE: 0.7,
        MIN_STOCK_THRESHOLD: 50,
        PAGE_RELOAD_INTERVAL: 10000, // 10 seconds in ms
        RANDOM_INTERVAL_MIN: 50,
        RANDOM_INTERVAL_MAX: 180,
        ENABLED: true
    };

    // Load configuration from storage or use defaults
    let config = Object.assign({}, DEFAULT_CONFIG, GM_getValue('buyerConfig', {}));

    let isReloadNeeded = false;
    let reloadInterval;

    // Create and inject configuration UI
    function createConfigUI() {
        const configDiv = document.createElement('div');
        configDiv.style.cssText = `
            position: fixed;
            top: 10%;
            left: 4%;
            background-color: rgba(240, 216, 176, 0.90);
            border: 1px solid #333;
            padding: 10px;
            z-index: 9999;
            max-width: 200px;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        `;

        configDiv.innerHTML = `
            <h3 style="margin: 0 0 10px 0;">Resource Buyer Settings</h3>
            <div style="display: grid; gap: 5px;">
                <label>
                    <input type="checkbox" id="buyer-enabled" ${config.ENABLED ? 'checked' : ''}>
                    Enable Buyer
                </label>
                <label>
                    Max Premium Points:
                    <input type="number" id="max-premium" value="${config.MAX_PREMIUM_POINTS}" min="0">
                </label>
                <label>
                    Premium Points Timeout (min):
                    <input type="number" id="premium-timeout" value="${config.PREMIUM_POINTS_TIMEOUT / 60000}" min="1">
                </label>
                <label>
                    Purchase Percentage:
                    <input type="number" id="purchase-percentage" value="${config.PURCHASE_PERCENTAGE * 100}" min="1" max="100" step="1">
                </label>
                <label>
                    Min Stock Threshold:
                    <input type="number" id="min-stock" value="${config.MIN_STOCK_THRESHOLD}" min="1">
                </label>
                <label>
                    Page Reload Interval (sec):
                    <input type="number" id="reload-interval" value="${config.PAGE_RELOAD_INTERVAL / 1000}" min="1">
                </label>
                <label>
                    Random Interval Min (ms):
                    <input type="number" id="random-min" value="${config.RANDOM_INTERVAL_MIN}" min="0">
                </label>
                <label>
                    Random Interval Max (ms):
                    <input type="number" id="random-max" value="${config.RANDOM_INTERVAL_MAX}" min="0">
                </label>
                <button id="save-config" style="margin-top: 5px;">Save Settings</button>
                <div id="save-status" style="color: green; display: none;">Settings saved!</div>
            </div>
        `;

        document.body.appendChild(configDiv);

        // Add event listener for save button
        document.getElementById('save-config').addEventListener('click', saveConfig);

        document.getElementById('buyer-enabled').addEventListener('change', function(e) {
            config.ENABLED = e.target.checked;
            GM_setValue('buyerConfig', config);
            restartIntervals();

            // Show save confirmation
            const saveStatus = document.getElementById('save-status');
            saveStatus.style.display = 'block';
            saveStatus.textContent = config.ENABLED ? 'Buyer enabled!' : 'Buyer disabled!';
            setTimeout(() => {
                saveStatus.style.display = 'none';
            }, 2000);
});

    }

    function saveConfig() {
        config = {
            ENABLED: document.getElementById('buyer-enabled').checked,
            MAX_PREMIUM_POINTS: parseInt(document.getElementById('max-premium').value),
            PREMIUM_POINTS_TIMEOUT: parseInt(document.getElementById('premium-timeout').value) * 60000,
            PURCHASE_PERCENTAGE: parseInt(document.getElementById('purchase-percentage').value) / 100,
            MIN_STOCK_THRESHOLD: parseInt(document.getElementById('min-stock').value),
            PAGE_RELOAD_INTERVAL: parseInt(document.getElementById('reload-interval').value) * 1000,
            RANDOM_INTERVAL_MIN: parseInt(document.getElementById('random-min').value),
            RANDOM_INTERVAL_MAX: parseInt(document.getElementById('random-max').value)
        };

        GM_setValue('buyerConfig', config);

        // Show save confirmation
        const saveStatus = document.getElementById('save-status');
        saveStatus.style.display = 'block';
        setTimeout(() => {
            saveStatus.style.display = 'none';
        }, 2000);

        // Restart intervals with new config
        restartIntervals();
    }

    function restartIntervals() {
        // Clear existing intervals
        if (reloadInterval) clearInterval(reloadInterval);

        // Set up new intervals if enabled
        if (config.ENABLED) {
            console.log(`Setting up automatic reload every ${config.PAGE_RELOAD_INTERVAL/1000} seconds`);
            reloadInterval = setInterval(function() {
                console.log('Executing scheduled reload...');
                window.location.reload();
            }, config.PAGE_RELOAD_INTERVAL);
        }
    }

    function checkPremiumPoints() {
        console.log('Checking premium points...');
        const marketStatusBar = document.getElementById('market_status_bar');
        if (marketStatusBar) {
            const premiumIcon = marketStatusBar.querySelector('.icon.header.premium');
            if (premiumIcon) {
                const parentElement = premiumIcon.closest('th');
                if (parentElement) {
                    const text = parentElement.textContent;
                    const points = parseInt(text.replace(/\D/g, ''));
                    console.log(`Current premium points: ${points}`);
                    if (points > config.MAX_PREMIUM_POINTS) {
                        console.log(`⚠️ Premium points exceed ${config.MAX_PREMIUM_POINTS}! Setting timeout...`);
                        return new Promise(resolve => setTimeout(resolve, config.PREMIUM_POINTS_TIMEOUT));
                    }
                }
            }
        }
        return Promise.resolve();
    }

    function checkForUsageWarningAndReload() {
        console.log('Checking for usage warning...');
        const errorMessages = document.querySelectorAll('.error_box');
        for (const errorBox of errorMessages) {
            if (errorBox.textContent.includes('premium') ||
                errorBox.textContent.includes('börse') ||
                errorBox.textContent.includes('market') ||
                errorBox.textContent.includes('exchange')) {
                console.log("⚠️ Usage warning detected! Initiating page reload...");
                window.location.reload();
                return;
            }
        }
        console.log("✓ No usage warning found");
    }

    function checkForErrorAndReload() {
        console.log('Checking for error image...');
        const errorImages = document.querySelectorAll('.error_image, img[src*="error"]');

        if (errorImages.length > 0) {
            console.log("⚠️ Error image detected! Initiating reload...");
            window.location.reload();
        } else {
            console.log("✓ No error images found");
        }
    }

    function clickBuyButton() {
        console.log('Attempting to click buy button...');
        const buyButton = document.querySelector('.btn-premium-exchange-buy');
        if (buyButton) {
            console.log("✓ Found buy button. Clicking...");
            buyButton.click();
        } else {
            console.error("❌ Buy button not found!");
        }
    }

    function clickConfirmButton() {
        console.log('Starting confirmation dialog check...');
        let counter = 0;
        const checkDialog = setInterval(function() {
            const confirmDialog = document.querySelector('.confirmation-box');
            if (confirmDialog && confirmDialog.style.display !== 'none') {
                clearInterval(checkDialog);
                console.log("✓ Confirmation dialog detected");
                const confirmButton = document.querySelector('.btn-confirm-yes');

                if (confirmButton) {
                    console.log("✓ Found confirm button");

                    // Add click event listener before clicking
                    confirmButton.addEventListener('click', function() {
                        console.log("✓ Button click confirmed");
                        const randomIntervalReload = Math.random() * (65 - 50) + 420;
                        console.log(`Scheduling page reload in ${randomIntervalReload.toFixed(2)}ms`);
                        setTimeout(function() {
                            console.log('Executing scheduled reload...');
                            window.location.reload();
                        }, randomIntervalReload);
                    });

                    console.log("Clicking button...");
                    confirmButton.click();
                } else {
                    console.error("❌ Confirm button not found! Initiating fallback reload...");
                    window.location.reload();
                }
            }
        }, 20);
    }

    async function checkAndBuyResources() {
        if (!config.ENABLED) {
            console.log('Buyer is disabled in settings');
            return;
        }

        console.log('-----------------------------------');
        console.log('Starting resource check cycle...');

        await checkPremiumPoints();
        checkForUsageWarningAndReload();
        console.log(`Current reload flag status: ${isReloadNeeded}`);

        console.log(`Purchase percentage set to: ${config.PURCHASE_PERCENTAGE * 100}%`);
        const resources = ['wood', 'stone', 'iron'];
        let anyResourceAvailable = false;

        for (let i = 0; i < resources.length; i++) {
            const resource = resources[i];
            const stockElement = document.getElementById(`premium_exchange_stock_${resource}`);

            if (!stockElement) {
                console.error(`❌ Could not find stock element for ${resource}!`);
                continue;
            }

            const stock = parseInt(stockElement.innerText.replace(/\D/g, ''), 10);
            console.log(`📊 ${resource.toUpperCase()}: Current stock: ${stock}`);

            if (stock > config.MIN_STOCK_THRESHOLD) {
                anyResourceAvailable = true;
                const amountToBuy = Math.floor(stock * config.PURCHASE_PERCENTAGE);
                console.log(`✓ ${resource.toUpperCase()}: Sufficient stock available. Attempting to buy: ${amountToBuy}`);

                const buyInputField = document.querySelector(`input[name="buy_${resource}"]`);
                if (buyInputField) {
                    buyInputField.value = amountToBuy;
                    console.log(`✓ ${resource.toUpperCase()}: Set buy amount to ${amountToBuy}`);
                    isReloadNeeded = false;

                    const randomIntervalBuy = Math.random() * (config.RANDOM_INTERVAL_MAX - config.RANDOM_INTERVAL_MIN) + config.RANDOM_INTERVAL_MIN;
                    console.log(`Scheduling buy click in ${randomIntervalBuy.toFixed(2)}ms`);
                    setTimeout(function() {
                        console.log('Executing scheduled buy click...');
                        clickBuyButton();
                    }, randomIntervalBuy);

                    const randomIntervalConfirm = Math.random() * (65 - 50) + 50;
                    console.log(`Scheduling confirm click in ${randomIntervalConfirm.toFixed(2)}ms`);
                    setTimeout(function() {
                        console.log('Executing scheduled confirm click...');
                        clickConfirmButton();
                    }, randomIntervalConfirm);

                    break;
                } else {
                    console.error(`❌ ${resource.toUpperCase()}: Buy input field not found!`);
                }
            } else {
                console.log(`ℹ️ ${resource.toUpperCase()}: Insufficient stock (${stock} < ${config.MIN_STOCK_THRESHOLD})`);
            }
        }

        isReloadNeeded = !anyResourceAvailable;
        console.log(`Resource check complete. Reload needed: ${isReloadNeeded}`);

        if (isReloadNeeded) {
            const randomInterval = Math.random() * (4000 - 50) + 200;
            console.log(`No resources available. Scheduling reload in ${randomInterval.toFixed(2)}ms`);
            setTimeout(function() {
                console.log('Executing scheduled reload due to no resources...');
                window.location.reload();
            }, randomInterval);
        }
    }

    // Initialize UI and start script
    console.log('Script initialized. Version 1.4.0');
    createConfigUI();

    const randomIntervalCheck = Math.random() * (config.RANDOM_INTERVAL_MAX - config.RANDOM_INTERVAL_MIN) + config.RANDOM_INTERVAL_MIN;
    console.log(`Initial check scheduled in ${randomIntervalCheck.toFixed(2)}ms`);
    setTimeout(function() {
        console.log('Executing initial resource check...');
        checkAndBuyResources();
    }, randomIntervalCheck);

    restartIntervals();

})();