您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Friendly Fire Protection in Browser and PDA
// ==UserScript== // @name NPO FF // @namespace https://www.torn.com/profiles.php?XID=3833584 // @version 2025-09-29 // @description Friendly Fire Protection in Browser and PDA // @author -Thelemite [3833584] // @match https://www.torn.com/profiles.php* // @match https://torn.com/profiles.php* // @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com // @run-at document-end // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; const Allies = [ { id: "10610", name: "NPO - Strength" }, // -- INDEX 0 { id: "44758", name: "NPO - Prosperity" }, // -- INDEX 1 { id: "12645", name: "NPO - Endurance" }, // -- INDEX 2 { id: "14052", name: "NPO - Serenity" }, // -- INDEX 3 { id: "18714", name: "NPO - Peace" }, // -- INDEX 4 { id: "26885", name: "NPO - Valour" }, // -- INDEX 5 { id: "19", name: "39th Street Killers" }, // -- INDEX 6 { id: "16312", name: "39th Street Killers X" }, // -- INDEX 7 { id: "7049", name: "39th Street Healers" }, // -- INDEX 8 { id: "22680", name: "39th Street Reapers" }, // -- INDEX 9 { id: "31764", name: "39th Street Warriors" }, // -- INDEX 10 { id: "36691", name: "Rabid Chihuahuas" }, // -- INDEX 11 { id: "11162", name: "InQuest" }, // -- INDEX 12 { id: "7197", name: "HeLa" }, // -- INDEX 13 { id: "30009", name: "White Rabbits" } // -- INDEX 14 ]; // Utility: wait for a selector to appear (handles PDA late DOM) function waitForSelector(selector, { root = document, timeout = 10000 } = {}) { return new Promise((resolve) => { const el = root.querySelector(selector); if (el) return resolve(el); const obs = new MutationObserver(() => { const found = root.querySelector(selector); if (found) { obs.disconnect(); resolve(found); } }); obs.observe(root.documentElement || root, { childList: true, subtree: true }); if (timeout > 0) { setTimeout(() => { obs.disconnect(); resolve(null); }, timeout); } }); } // Extract factionId from /factions.php?step=profile&ID=... links function getFactionId() { const anchors = document.querySelectorAll('a[href*="/factions.php?step=profile&ID="]'); for (const a of anchors) { try { const url = new URL(a.getAttribute('href'), location.href); if (url.pathname.endsWith('/factions.php') && url.searchParams.get('step') === 'profile') { const id = url.searchParams.get('ID'); if (id) return String(id).trim(); } } catch { /* ignore malformed hrefs */ } } return null; } // (Optional) userId, if you need it later function getUserIdFromAttackBtn(btn) { const id = btn?.id ?? ''; const parts = id.split('-'); return parts.length ? parts[parts.length - 1] : null; } // Update decorateAndIntercept to accept allyName function decorateAndIntercept(attackBtn, factionId, allyName) { if (!attackBtn) return; if (attackBtn.dataset.allyDecorated === '1') return; attackBtn.dataset.allyDecorated = '1'; // Positioning for overlay const cs = getComputedStyle(attackBtn); if (cs.position === 'static') attackBtn.style.position = 'relative'; // Green X overlay (slightly smaller for mobile) const x = document.createElement('span'); x.textContent = '✕'; x.setAttribute('aria-hidden', 'true'); x.style.position = 'absolute'; x.style.top = '2px'; x.style.right = '2px'; x.style.fontWeight = '900'; x.style.fontSize = '36px'; x.style.lineHeight = '1'; x.style.padding = '2px 4px'; x.style.borderRadius = '4px'; x.style.background = 'rgba(0, 128, 0, 0.15)'; x.style.color = '#0f0'; x.style.pointerEvents = 'none'; x.title = `Ally faction (${allyName}) – confirm before attacking`; attackBtn.appendChild(x); // Confirm dialog allowing proceed const onAttemptAttack = (e) => { e.preventDefault(); e.stopPropagation(); const proceed = confirm( `This player is in an allied faction (${allyName}).\n\nAre you sure you want to attack?` ); if (!proceed) return; const href = attackBtn.getAttribute('href'); if (!href) return; // Respect modifier keys / middle click if (e.metaKey || e.ctrlKey || e.button === 1) { window.open(href, '_blank'); } else { window.location.href = href; } }; attackBtn.addEventListener('click', onAttemptAttack, { capture: true }); } async function init() { // Wait for either: faction link appears OR just proceed after a beat await waitForSelector('a[href*="/factions.php?step=profile&ID="]', { timeout: 5000 }); const factionId = getFactionId(); const allyObj = Allies.find(a => String(a.id) === String(factionId)); const isAlly = !!allyObj; // Log for debugging const attackBtnNow = document.querySelector('a.profile-button-attack'); const userId = getUserIdFromAttackBtn(attackBtnNow); console.log(`NPO FF: User:${userId} Faction:${factionId} IsAlly:${isAlly}`); if (!isAlly) return; // Ensure we catch the attack button even if it renders later const attackBtn = await waitForSelector('a.profile-button-attack', { timeout: 8000 }); if (!attackBtn) return; decorateAndIntercept(attackBtn, factionId, allyObj.name); } // Run at document-end, plus handle full load as a fallback init(); window.addEventListener('load', init, { once: true }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址