FreeForAll - AttackButtons

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

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 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);
})();