Torn Chain Panel

This is a work in progress, it is no where near completed. It is NOT for use for anyone other than my faction. It is probably not even a good script lol. thanks for reading. heres what it does. A collapsible utility panel for my faction to manually fetch their assigned chain number and a hit timer during wars. This tool helps faction members stay organized during chain events without having someone always there to monitor the chain.

Este script não deve ser instalado diretamente. É uma biblioteca destinada a ser incluída por outros scripts através da diretiva de metadados // @require https://update.greasyfork.org/scripts/544476/1637545/Torn%20Chain%20Panel.js

Terá de instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

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

Terá de instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Terá de instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Terá de instalar uma extensão como Tampermonkey para instalar este script.

Terá de instalar uma extensão de gestão de scripts de utilizador para instalar este script.

(Já tenho um gestor de scripts de utilizador, deixe-me instalá-lo!)

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

(Já tenho um gestor de estilos de utilizador, deixe-me instalá-lo!)

// ==UserScript==
// @name         Torn Chain Panel
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  Collapsible panel for chain # + timer
// @author       BuzzC137
// @match        https://www.torn.com/*
// @grant        none
// @license      Proprietary
// ==/UserScript==

/*
Copyright © 2025 BuzzC137

This script is proprietary and not open source.

You MAY NOT:
- Copy, modify, distribute, or use this script in any form without explicit written permission from the author.

Exception:
Torn City developers and staff are permitted to review or access this script for moderation, verification, or security purposes.

Unauthorized use may result in revocation of access or further action.
*/


(function () {
  'use strict';

  const discordUsername = 'buzzc137';

  const styles = `
    #chainPanel {
      position: fixed;
      top: 100px;
      left: 20px;
      background: rgba(24, 24, 24, 0.95);
      color: #ccc;
      font-family: Verdana, sans-serif;
      font-size: 12px;
      border: 1px solid #555;
      border-radius: 5px;
      padding: 10px;
      z-index: 9999;
      width: 220px;
      box-shadow: 0 0 10px #000;
    }
    #chainPanel.collapsed .panel-body {
      display: none;
    }
    #chainPanel .panel-header {
      font-weight: bold;
      color: #0f0;
      cursor: move;
      margin-bottom: 8px;
    }
    #chainPanel button,
    #chainPanel input {
      width: 100%;
      margin-bottom: 6px;
      padding: 6px;
      border: none;
      border-radius: 3px;
      font-size: 11px;
    }
    #chainPanel button {
      background: #333;
      color: white;
      cursor: pointer;
    }
    #chainPanel button:hover {
      background: #555;
    }
    #chainPanel .toggle {
      background: #1c1c1c;
      color: #aaa;
      font-size: 10px;
      text-align: center;
      padding: 4px;
      border-top: 1px solid #444;
      cursor: pointer;
    }
    #chainTabs {
      display: flex;
      justify-content: space-around;
      margin-bottom: 6px;
    }
    #chainTabs button {
      font-size: 10px;
      padding: 4px;
    }
  `;

  const styleTag = document.createElement('style');
  styleTag.innerText = styles;
  document.head.appendChild(styleTag);

  const panel = document.createElement('div');
  panel.id = 'chainPanel';
  panel.innerHTML = `
    <div class="panel-header">Chain Tool</div>
    <div class="panel-body">
      <input type="number" id="chainTimerInput" placeholder="Timer (sec)">
      <button id="getChainBtn">Get My Chain #</button>
      <button id="startTimerBtn">Start Timer</button>
      <div id="chainTabs">
        <button disabled>Tab 1</button>
        <button disabled>Tab 2</button>
      </div>
    </div>
    <div class="toggle">▲ Collapse</div>
  `;
  document.body.appendChild(panel);

  // Collapse toggle
  const toggle = panel.querySelector('.toggle');
  toggle.addEventListener('click', () => {
    panel.classList.toggle('collapsed');
    toggle.innerText = panel.classList.contains('collapsed') ? '▼ Expand' : '▲ Collapse';
  });

  // Drag logic
  const header = panel.querySelector('.panel-header');
  let isDragging = false, offsetX = 0, offsetY = 0;
  header.addEventListener('mousedown', (e) => {
    isDragging = true;
    offsetX = e.clientX - panel.offsetLeft;
    offsetY = e.clientY - panel.offsetTop;
  });
  document.addEventListener('mousemove', (e) => {
    if (isDragging) {
      panel.style.left = `${e.clientX - offsetX}px`;
      panel.style.top = `${e.clientY - offsetY}px`;
    }
  });
  document.addEventListener('mouseup', () => isDragging = false);

  // Fetch Chain Number
  const fetchBtn = panel.querySelector('#getChainBtn');
  fetchBtn.addEventListener('click', () => {
    fetch(`https://removing-maldives-driving-money.trycloudflare.com/chain/${discordUsername}`)
      .then(res => res.json())
      .then(data => {
        if (data.chain) {
          alert(`Your assigned chain number is: #${data.chain}`);
        } else {
          alert('You don’t have a chain number yet.');
        }
      })
      .catch(err => {
        alert('Error fetching chain number. Is the bot running?');
        console.error('Fetch error:', err);
      });
  });

  // Timer logic
  let timer;
  panel.querySelector('#startTimerBtn').addEventListener('click', () => {
    const seconds = parseInt(document.querySelector('#chainTimerInput').value) || 10;

    // Red flash
    const flash = document.createElement('div');
    flash.style.position = 'fixed';
    flash.style.top = 0;
    flash.style.left = 0;
    flash.style.width = '100%';
    flash.style.height = '100%';
    flash.style.backgroundColor = 'red';
    flash.style.opacity = '0.5';
    flash.style.zIndex = 999;
    document.body.appendChild(flash);
    setTimeout(() => document.body.removeChild(flash), 500);

    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      const audio = new Audio('https://www.soundjay.com/button/sounds/beep-07.mp3');
      audio.play();
      console.log("Timer complete – make your hit!");
    }, seconds * 1000);
  });
})();