// ==UserScript==
// @name Official [TriX] Bot Script by painsel
// @version 0.0.6 Test Build
// @description A bot script for territorial.io with a modern UI to simulate typing usernames and clan tags.
// @author painsel
// @license MIT
// @homepageURL https://greasyfork.org/en/scripts/549132-trix-executor-beta-for-territorial-io
// @match https://territorial.io/
// @grant GM_addStyle
// @namespace http://tampermonkey.net/
// ==/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> Bot Script
</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.
*/
function simulateTyping(element, text, style, onComplete) {
let i = 0;
element.value = '';
element.focus();
function typeCharacter() {
if (i < text.length) {
element.value += text.charAt(i);
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;
localStorage.setItem(STORAGE_KEY, JSON.stringify({ clanTag, username }));
}
/**
* Loads user settings from localStorage.
*/
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);
}
}
}
/**
* Initializes the UI and adds all event listeners.
*/
function initializeUI() {
if (document.getElementById('trix-container')) return;
GM_addStyle(trixCSS);
document.body.insertAdjacentHTML('beforeend', trixHTML);
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');
loadSettings();
clanTagInput.addEventListener('input', saveSettings);
usernameInput.addEventListener('input', saveSettings);
startBtn.addEventListener('click', () => {
const clanTag = clanTagInput.value.trim();
const username = usernameInput.value.trim();
const typingStyle = document.querySelector('input[name="trix-typing-style"]:checked').value;
// *** CHANGE: Target the correct input field ID '#input0' ***
const nameInput = document.querySelector('#input0');
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';
});
});
let isDragging = false, 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 Logic ---
/**
* Finds the multiplayer button by its text content.
* @returns {HTMLElement|null} The button element or null if not found.
*/
function findMultiplayerButton() {
const buttons = document.querySelectorAll('button');
for (const btn of buttons) {
if (btn.innerText && btn.innerText.includes('Multiplayer')) {
return btn;
}
}
return null;
}
/**
* Waits for the main game UI (specifically the Multiplayer button) to appear, then executes a callback.
* @param {function} callback - The function to execute once the UI is ready.
*/
function waitForGameUI(callback) {
if (findMultiplayerButton()) {
callback();
return;
}
const observer = new MutationObserver((mutations, obs) => {
if (findMultiplayerButton()) {
obs.disconnect();
callback();
}
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
}
// Wait for the game's main menu to be ready before initializing our script's UI.
waitForGameUI(initializeUI);
/*
The MIT License (MIT)
Copyright (c) 2024 painsel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
})();