Official [TriX] Bot Script by painsel

A bot script for territorial.io with a modern UI to simulate typing usernames and clan tags.

Version vom 17.09.2025. Aktuellste Version

// ==UserScript==
// @name         Official [TriX] Bot Script by painsel
// @version      0.0.1 Test Build
// @description  A bot script for territorial.io with a modern UI to simulate typing usernames and clan tags.
// @author       painsel
// @homepageURL  https://greasyfork.org/en/scripts/549132-trix-executor-beta-for-territorial-io
// @match        https://territorial.io/
// @grant        GM_addStyle
// @namespace    http://tampermonkey.net/
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    const STORAGE_KEY = 'd122';

    // --- 1. UI Styling (VS Code Theme) ---
    const trixCSS = `
        :root {
            --trix-bg: #1e1e1e;
            --trix-bg-light: #252526;
            --trix-header-bg: #333333;
            --trix-border: #3c3c3c;
            --trix-text: #d4d4d4;
            --trix-text-secondary: #cccccc;
            --trix-blue-accent: #007acc;
            --trix-button-bg: #0e639c;
            --trix-button-hover-bg: #1177bb;
            --trix-input-bg: #3c3c3c;
        }

        #trix-container {
            position: fixed;
            top: 20px;
            left: 20px;
            width: 280px;
            background-color: var(--trix-bg-light);
            border: 1px solid var(--trix-border);
            border-radius: 6px;
            color: var(--trix-text);
            font-family: 'Consolas', 'Menlo', 'Courier New', monospace;
            font-size: 14px;
            z-index: 99999;
            box-shadow: 0 5px 20px rgba(0,0,0,0.5);
            user-select: none;
            overflow: hidden;
        }

        #trix-header {
            background-color: var(--trix-header-bg);
            padding: 8px 12px;
            cursor: move;
            font-weight: bold;
            border-bottom: 1px solid var(--trix-border);
        }

        #trix-header a {
            color: var(--trix-blue-accent);
            text-decoration: none;
        }
         #trix-header a:hover {
            text-decoration: underline;
        }

        #trix-body {
            padding: 15px;
            display: flex;
            flex-direction: column;
            gap: 15px;
        }

        .trix-input-group {
            display: flex;
            flex-direction: column;
            gap: 5px;
        }

        .trix-input-group label {
            font-size: 13px;
            color: var(--trix-text-secondary);
        }

        .trix-input-group input[type="text"],
        .trix-input-group select {
            background-color: var(--trix-input-bg);
            border: 1px solid var(--trix-border);
            color: var(--trix-text);
            padding: 8px;
            border-radius: 4px;
            font-family: inherit;
            outline: none;
            transition: border-color 0.2s;
        }

        .trix-input-group input[type="text"]:focus,
        .trix-input-group select:focus {
            border-color: var(--trix-blue-accent);
        }

        #trix-start-btn {
            background-color: var(--trix-button-bg);
            color: white;
            border: none;
            padding: 10px;
            border-radius: 4px;
            font-family: inherit;
            font-size: 14px;
            font-weight: bold;
            cursor: pointer;
            transition: background-color 0.2s;
        }

        #trix-start-btn:hover {
            background-color: var(--trix-button-hover-bg);
        }

        #trix-start-btn:disabled {
            background-color: #5a5a5a;
            cursor: not-allowed;
        }

        .trix-radio-group {
            display: flex;
            gap: 15px;
        }
        .trix-radio-group label {
            display: flex;
            align-items: center;
            gap: 5px;
            cursor: pointer;
        }
    `;

    // --- 2. UI HTML Structure ---
    const trixHTML = `
        <div id="trix-container">
            <div id="trix-header">
                Official <a href="https://greasyfork.org/en/scripts/549132-trix-executor-beta-for-territorial-io" target="_blank">TriX</a> Executor
            </div>
            <div id="trix-body">
                <div class="trix-input-group">
                    <label for="trix-clan-tag">Clan Tag (e.g., TriX)</label>
                    <input type="text" id="trix-clan-tag" placeholder="Leave empty for no tag">
                </div>
                <div class="trix-input-group">
                    <label for="trix-username">Username</label>
                    <input type="text" id="trix-username" placeholder="Enter your name">
                </div>
                <div class="trix-input-group">
                    <label>Typing Style</label>
                    <div class="trix-radio-group">
                        <label>
                            <input type="radio" name="trix-typing-style" value="custom" checked> Custom
                        </label>
                        <label>
                            <input type="radio" name="trix-typing-style" value="random"> Random
                        </label>
                    </div>
                </div>
                <button id="trix-start-btn">Begin Typing Simulation</button>
            </div>
        </div>
    `;

    // --- 3. Core Logic ---

    /**
     * Simulates human-like typing into an input field.
     * @param {HTMLInputElement} element - The input element to type into.
     * @param {string} text - The text to type.
     * @param {string} style - The typing style ('custom' or 'random').
     * @param {function} onComplete - Callback function when typing is finished.
     */
    function simulateTyping(element, text, style, onComplete) {
        let i = 0;
        element.value = ''; // Clear the field first
        element.focus();

        function typeCharacter() {
            if (i < text.length) {
                element.value += text.charAt(i);
                // Dispatch an 'input' event to make sure frameworks like React/Vue detect the change
                element.dispatchEvent(new Event('input', { bubbles: true }));
                i++;

                const delay = style === 'random' ? Math.random() * 150 + 50 : 75;
                setTimeout(typeCharacter, delay);
            } else {
                element.blur();
                if (onComplete) onComplete();
            }
        }
        typeCharacter();
    }

    /**
     * Saves user settings to localStorage.
     */
    function saveSettings() {
        const clanTag = document.getElementById('trix-clan-tag').value;
        const username = document.getElementById('trix-username').value;
        const settings = {
            clanTag,
            username
        };
        localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
    }

    /**
     * Loads user settings from localStorage and applies them to the UI.
     */
    function loadSettings() {
        const settings = localStorage.getItem(STORAGE_KEY);
        if (settings) {
            try {
                const { clanTag, username } = JSON.parse(settings);
                document.getElementById('trix-clan-tag').value = clanTag || '';
                document.getElementById('trix-username').value = username || '';
            } catch (e) {
                console.error('[TriX] Failed to load settings:', e);
                localStorage.removeItem(STORAGE_KEY);
            }
        }
    }

    /**
     * Initializes the UI and adds all event listeners.
     */
    function initializeUI() {
        if (document.getElementById('trix-container')) return; // Already initialized

        // Inject CSS and HTML
        GM_addStyle(trixCSS);
        document.body.insertAdjacentHTML('beforeend', trixHTML);

        // Get UI elements
        const container = document.getElementById('trix-container');
        const header = document.getElementById('trix-header');
        const clanTagInput = document.getElementById('trix-clan-tag');
        const usernameInput = document.getElementById('trix-username');
        const startBtn = document.getElementById('trix-start-btn');

        // Load saved settings
        loadSettings();

        // Add event listeners for saving settings on change
        clanTagInput.addEventListener('input', saveSettings);
        usernameInput.addEventListener('input', saveSettings);

        // Event listener for the main button
        startBtn.addEventListener('click', () => {
            const clanTag = clanTagInput.value.trim();
            const username = usernameInput.value.trim();
            const typingStyle = document.querySelector('input[name="trix-typing-style"]:checked').value;
            const nameInput = document.querySelector('#name'); // The game's name input

            if (!username) {
                alert('[TriX] Please enter a username.');
                return;
            }

            if (!nameInput) {
                alert('[TriX] Could not find the game\'s name input field.');
                return;
            }

            const fullName = clanTag ? `[${clanTag}] ${username}` : username;

            startBtn.disabled = true;
            startBtn.textContent = 'Typing...';

            simulateTyping(nameInput, fullName, typingStyle, () => {
                startBtn.disabled = false;
                startBtn.textContent = 'Begin Typing Simulation';
            });
        });

        // Make the UI draggable
        let isDragging = false;
        let offsetX, offsetY;

        header.addEventListener('mousedown', (e) => {
            isDragging = true;
            offsetX = e.clientX - container.offsetLeft;
            offsetY = e.clientY - container.offsetTop;
            document.addEventListener('mousemove', onMouseMove);
            document.addEventListener('mouseup', onMouseUp);
        });

        function onMouseMove(e) {
            if (isDragging) {
                container.style.left = `${e.clientX - offsetX}px`;
                container.style.top = `${e.clientY - offsetY}px`;
            }
        }

        function onMouseUp() {
            isDragging = false;
            document.removeEventListener('mousemove', onMouseMove);
            document.removeEventListener('mouseup', onMouseUp);
        }
    }

    // --- 4. Script Execution ---

    // Wait for the game's UI to be available before initializing our UI
    const gameReadyCheck = setInterval(() => {
        // We check for the #name input, as it's a key part of the main menu
        if (document.querySelector('#name')) {
            clearInterval(gameReadyCheck);
            initializeUI();
        }
    }, 500);

})();