FreeForAll - AttackButtons

Always show Attack column for your faction; toggle all grey "Attack" labels into real links (both teams).

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         FreeForAll - AttackButtons
// @namespace    http://tampermonkey.net/
// @version      5.2
// @description  Always show Attack column for your faction; toggle all grey "Attack" labels into real links (both teams).
// @match        https://www.torn.com/factions.php*
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
  'use strict';

  // --- settings ---
  const DEBUG = true;

  // toggle state: when true, convert grey Attack spans to real links; when false, revert to grey spans
  let linksEnabled = true;

  const log = (...a) => DEBUG && console.log('[AttackToggle]', ...a);

  // --- CSS: keep your-faction Attack column visible; style our links ---
  (function addStyles() {
    const css = `
      /* Force show Attack column in your-faction (header + cells) */
      .tab-menu-cont.your-faction .attack,
      .tab-menu-cont.your-faction .attack.left,
      .tab-menu-cont.your-faction .attack___wBWp2 {
        display: inline-block !important;
        visibility: visible !important;
        opacity: 1 !important;
        pointer-events: auto !important;
      }

      /* Make sure header keeps space for Attack */
      .tab-menu-cont.your-faction .members-cont > .white-grad .attack {
        display: inline-block !important;
      }

      /* Our injected attack link */
      a.custom-attack-button {
        text-decoration: none !important;
        padding: 0px 2px;
        border-radius: 2px;
        cursor: pointer;
        margin-left: 4px;
        color: white !important;
        background: #0078d4 !important;
        display: inline-block;
      }
    `;
    const s = document.createElement('style');
    s.textContent = css;
    document.head.appendChild(s);
  })();
function fixYourFactionWidth() {
    const faction = document.querySelector('.tab-menu-cont.your-faction');
    if (!faction) return;

    // Shrink the container width to leave room for the Attack column
    //faction.style.width = 'calc(50%)'; // tweak 40px as needed
    //faction.style.boxSizing = 'border-box';
    faction.querySelectorAll(`div[class*="points"]`).forEach(cell => {
            cell.style.width = '10%'; // adjust % as needed
            cell.style.minWidth = '0'; // allow shrinking
        });
    faction.querySelectorAll(`div[class*="attack"]`).forEach(cell => {
            cell.style.width = '3%'; // adjust % as needed
            cell.style.minWidth = '0'; // allow shrinking
        });
    faction.querySelectorAll(`div[class*="level"]`).forEach(cell => {
            cell.style.width = '8%'; // adjust % as needed
            cell.style.minWidth = '0'; // allow shrinking
        });
}
  // --- helpers ---
  function showElementHard(el) {
    if (!el) return;
    el.style.setProperty('display', 'inline-block', 'important');
    el.style.setProperty('visibility', 'visible', 'important');
    el.style.setProperty('opacity', '1', 'important');
    el.style.setProperty('pointer-events', 'auto', 'important');
  }

  function ensureYourFactionHeader() {
    const root = document.querySelector('.tab-menu-cont.your-faction');
    if (!root) return;

    const header = root.querySelector('.members-cont > .white-grad');
    if (!header) return;

    let attackHeader = header.querySelector('.attack');
    if (!attackHeader) {
      attackHeader = document.createElement('div');
      attackHeader.className = 'attack left attack___wBWp2 tab___UztMc';
      attackHeader.textContent = 'Attack';
      header.appendChild(attackHeader);
      log('Created Attack header for your faction');
    }
    showElementHard(attackHeader);
  }

  function ensureYourFactionCells() {
    // Make sure each teammate row has an attack cell so the column keeps shape.
    const yourRows = document.querySelectorAll('.tab-menu-cont.your-faction ul.members-list li.your');
    yourRows.forEach(li => {
      let attackCell = li.querySelector('.attack');
      if (!attackCell) {
        attackCell = document.createElement('div');
        attackCell.className = 'attack left attack___wBWp2';
        // Insert near the end like Torn usually does
        const clearEl = li.querySelector('.clear');
        li.insertBefore(attackCell, clearEl || null);
      }
      showElementHard(attackCell);
    });
  }

  function xidFromRow(li) {
    const profileLink = li.querySelector('a[href^="/profiles.php?XID="]');
    if (!profileLink) return null;
    const m = profileLink.href.match(/XID=(\d+)/);
    return m ? m[1] : null;
  }

  // Convert the attack cell for a single row according to linksEnabled
function transformAttackCellForRow(li) {
    let attackCell = li.querySelector('.attack');
    if (!attackCell) return;

    // Always keep the cell visible
    if (li.classList.contains('your')) showElementHard(attackCell);

    // Only create the link once
    let link = attackCell.querySelector('a.custom-attack-button');
    if (!link && linksEnabled) {
        const xid = xidFromRow(li);
        if (!xid) return;
        link = document.createElement('a');
        link.href = `https://www.torn.com/loader.php?sid=attack&user2ID=${xid}`;
        link.textContent = 'Attack';
        link.className = 'custom-attack-button';
        link.target = '_blank';
        link.rel = 'noopener noreferrer';
        attackCell.appendChild(link);

        // Hide the grey span if present
        attackCell.querySelectorAll('span.t-gray-9').forEach(s => s.style.display = 'none');
    }

    // Instead of removing/adding nodes, just show/hide via style
    if (link) link.style.display = linksEnabled ? 'inline-block' : 'none';
    attackCell.querySelectorAll('span.t-gray-9').forEach(span => {
        span.style.display = linksEnabled ? 'none' : 'inline-block';
    });
}

  function transformAllRows() {
    // Always keep your-faction column visible
    fixYourFactionWidth();
    ensureYourFactionHeader();
    ensureYourFactionCells();

    // Apply toggle behavior to ALL rows (both teams)
    const rows = document.querySelectorAll('ul.members-list > li');
    rows.forEach(transformAttackCellForRow);
  }

  // --- toggle button ---
  function createToggleButton() {
    const button = document.createElement('button');
    button.textContent = 'Attack Links: ON';
    button.style.position = 'fixed';
    button.style.bottom = '5%';
    button.style.right = '10px';
    button.style.zIndex = '2147483647';
    button.style.padding = '6px 10px';
    button.style.backgroundColor = '#008CBA';
    button.style.color = 'white';
    button.style.border = 'none';
    button.style.borderRadius = '5px';
    button.style.cursor = 'pointer';
    button.style.fontSize = '14px';
    button.style.boxShadow = '0 0 5px rgba(0,0,0,0.3)';

button.addEventListener('click', () => {
    linksEnabled = !linksEnabled;
    button.textContent = `Attack Links: ${linksEnabled ? 'ON' : 'OFF'}`;
    button.style.backgroundColor = linksEnabled ? '#008CBA' : '#777';
    // This now only toggles visibility, no DOM removal
    transformAllRows();
});

    document.body.appendChild(button);
  }

  // --- observers / boot ---
  let debounce;
  const mo = new MutationObserver(() => {
    clearTimeout(debounce);
    debounce = setTimeout(transformAllRows, 200);
  });

  function start() {
    createToggleButton();
    transformAllRows();
    mo.observe(document.body, { childList: true, subtree: true });
    log('Initialized');
  }

  // Delay a touch to let Torn render
  setTimeout(start, 600);
})();